How to access members through a void pointer

前端 未结 4 1456
我寻月下人不归
我寻月下人不归 2021-01-15 20:29

Started by trying to write a small program to translate basic arithmetic into English, I end up building a binary tree(which is inevitably very unbalanced) to represent the

4条回答
  •  一整个雨季
    2021-01-15 21:05

    If you know the offset at where your struct member is you can do pointer arithmetic and then cast to the appropriate type according to the value of entity_flag.

    I would strongly suggest to align both structures in bytes and use the same number of bytes for oprt and digit.

    Also, if you only have oprt and digit "types" in your tree you could sacrifice the first bit of precision to flag for digit or oprt and save the space needed for unsigned char entity_flag. If you use a single 4 bytes int var for both oprt and digit and use the first bit to encode the type you can extract a digit by (using the union solution pattern: proposed in the thread)

    typedef union {
        struct {
            int code;
            expr * l_expr;
            expr * r_expr;
        } oprt;
        struct {
           int val;
        } digit;
    } expr;
    
    expr *x;
    int raw_digit = x->digit.val;
    
    int digit = raw_digit | ((0x4000000 & raw_digit) << 1 ) // preserves sign in 2's complement 
    
    x->digit.val = digit | 0x8000000                       // assuming MSB==1 means digit
    

    Using union does not necessarily uses more memory for digits. Basically a digit only takes 4 bytes. So every time you need to alloc a digit type expr you can simply call malloc(4), cast the results to *expr, and set the MSB to 1 accordingly. If you encode and decode expr pointers without bugs, you'll never try to reach beyond the 4th bytes of a "digit" type expr ... hopefully. I don't recommend this solution if you need safety ^_^

    To check for expr types easily, you can use bitfield inside the union I believe:

    typedef union {
       struct {
           int code;
           expr * l_expr;
           expr * r_expr;
       } oprt;
       struct {
           int val;
       } digit;
       struct {
           unsigned int is_digit : 1;
           int : 31; //unused
       } type;
    

    } expr;

提交回复
热议问题