1
votes

I have a the following typedef

 typedef struct {   
         const char *name;
         void *variable;
         int type;
         int *present;
  } parse_t;

and structures having a variable and an integer having the same name with an _b appended.

For example:

 typedef struct {
     char test[12]; 
     int test_b;

     long id; 
     int id_b;

  } record_t;

What I'm trying to do is a macro to define records in the parse_t struct that will write it depending on the type of the variable;

For example:

    record_t record;

    prase_t parse[] = 
    {
        ROW("TEST", record, test, TYPE_STRING);
        ROW("ID", record, id, TYPE_INT);
    }

with ROW doing the following:

  • Setting the name value
  • Based on the type, if it's TYPE_STRING, use record.<variable> as the variable, else use &(record.id)
  • Set the type value
  • append _b to the variable name passed to the macro and use it in the row.

I tried many options and the closest was the following

 #define ROW(x, y, z, v) {x, (TYPE_STRING == v) ? y.z:&(y.z), v, &(y.z##_b)}

but I'm getting errors using it like the following

     The ":" operator is not allowed between "char[4]" and "char(*)[4]".

I appreciate any help. I guess I can always use two different macros one for the string type and another for the int for example, but I'm trying to simplify it as much as I can.

1
During Macro expansion (first step of a C program compilaton) only a substition is made , no evaluation, except for artithmetic computation of constants. Thus (TYPE_STRING == v) ? will not be evaluated, it will be put into your structure and generate illegal C code . Try the -E flag of gcc to see the result of macro expansion .Louis Hugues
Hi @SioulSeuguh , thanks but I don't really have control over the compiler, I only can change in the codewassim
Since your last statement is but I'm trying to simplify it as much as I can. I suggest (for simplicity and readability) just define two structs, and surround them with macros to expose the one you want to use at compile time. This will be more readable to anyone having to maintain your code :)ryyker

1 Answers

1
votes

Why do you need the TYPE_STRING test? taking the address of an array is a noop if you're just going to convert it to a void *, since the array will decay to a pointer in that case. So just use

#define ROW(x,y,z,v)  { x, &(y.z), v, &(y.z##_b) }