CodeTry
CodeTry

Reputation: 312

initializing structure using macros

I have a structure and i am using preprocessing macro to populate the arrays in struct.

#include <stdio.h>
void init_data();
typedef struct _abc{
        int a[10][10];
        int b[5][5];
}abc;
static abc q_abc[]= {
                #define XYZ(x,y,z) [x]={.a[y][z]=1,.b[y][z]=1},
                 XYZ(1,2,3)
                 XYZ(1,3,2)

};
static abc q_abc1[5];
void init_data()
{
 #define XYZW(x,y,z) q_abc1[x].a[y][z] =1;
  XYZW(1,2,3)
  XYZW(1,3,2)
}
int main()
{
        printf("\n  %d  %d\n",q_abc[1].a[2][3]);
        init_data();
        printf("\n %d  %d\n",q_abc1[1].a[2][3]);
        return 0;
}

I am initializing struct q_abc using macro. But the problem here is value set during macro call to XYZ(1,2,3) is reset to the default 0 during call to next macro call XYZ(1,3,2). I can understand as not specifying any explicit initializer will set the array to the default 0.

To avoid this I used the init_data approach .Here i am not initializing the array but assigning, so arrays will have all the values from all macro calls intact. but then problem here is , if data is huge or number of macro calls are huge, the func call will take little time to complete which adds an overhead to my exe run time.

is there any way to achieve init_data sort of behavior during variable definition itself ? any suggestions ?

Upvotes: 0

Views: 819

Answers (1)

This is a case where turning on warnings would have helped you. Compiling your code with GCC gives me this:

main.cpp:8:40: warning: initialized field overwritten [-Woverride-init]
                 #define XYZ(x,y,z) [x]={.a[y][z]=1,.b[y][z]=1},
                                        ^
main.cpp:10:18: note: in expansion of macro 'XYZ'
                  XYZ(1,3,2)
                  ^~~
main.cpp:8:40: note: (near initialization for 'q_abc[1]')
                 #define XYZ(x,y,z) [x]={.a[y][z]=1,.b[y][z]=1},
                                        ^
main.cpp:10:18: note: in expansion of macro 'XYZ'
                  XYZ(1,3,2)

And for good reason. A brace initializer will initialize all the fields, even if you omit explicit initializers for some (those will be zero). By writing X(1,..) X(1,...) you initialize the same index twice. You can't split it into two macro expansions like you try. It must be in a single one, if you really wish to use a macro.

Personally, I wouldn't faff about with macros. Designated initializers make the code readable enough even without hiding them behind a macro.

Upvotes: 3

Related Questions