SamLi
SamLi

Reputation: 105

Using define macro to initialize structure object in C

#define DEFAULT_XXX (NUM_1, NUM_2 )      \
    {
     .data_time = NUM_1,                         \
     .data = NUM_2,                         
    };

typedef struct DEFAULT_XXX_STRUCT {
    int* data_time; 
    int* data;
} SomeSetting;

SomeSetting HAHASetting = DEFAULT_XXX(123,456) ;

I want to ask why this kind of define can init the "HAHASetting" object. especially why we can just .data and .data_time inside the #define?

Upvotes: 1

Views: 6215

Answers (2)

First, the provided code is faulty. I guess it looks like this, from where you got it:

#define DEFAULT_XXX( NUM_1, NUM_2 )      \
    {                                    \
      .data_time = NUM_1,                \
      .data = NUM_2                      \   
    };

typedef struct DEFAULT_XXX_STRUCT {
    int data_time; 
    int data;
} SomeSetting;

SomeSetting HAHASetting = DEFAULT_XXX(123,456) ;
  1. Note that there need to be a \ after each line which belongs to the #define macro, except the last one with the terminating ;. The \ has the effect that the compiler will consider the next line to the macro.

    If you omit to place \ at lines where another part of the macro is following in another line, this would be a syntax error which the compiler will hint you very soon at the attempt to compiling.

    Without all \'s you need to write the whole macro in one line, like:

    #define DEFAULT_XXX( NUM_1, NUM_2 ) { .data_time = NUM_1, .data = NUM_2 };
    
  2. DEFAULT_XXX needs to be followed by its list ( NUM_1, NUM_2 ) without a space between.

  3. The structure members data_time and data are both of type pointer to int, but the passed values are of type int. There is a type mismatch. This is a C syntax violation. If they should be assigned with int values they should be of type int, not int *.

    See this question for more informations:

    "Pointer from integer/integer from pointer without a cast" issues


Example:

#include <stdio.h>

#define DEFAULT_XXX( NUM_1, NUM_2 )      \
    {                                    \
     .data_time = NUM_1,                 \
     .data = NUM_2                       \
    };

typedef struct DEFAULT_XXX_STRUCT {
    int data_time; 
    int data;
} SomeSetting;

int main (void)
{
    SomeSetting HAHASetting = DEFAULT_XXX(123,456);

    printf("%d\n", HAHASetting.data_time);
    printf("%d\n", HAHASetting.data);
}

Output:

123
456

I want to ask why this kind of #define can init(ialize) the "HAHASetting" object?

#define macros are basically used to replace text, act like functions or to be used as initializer as provided in this example (There might be other uses but to cover all is too much for now and irrelevant to answer your question as well). The C preprocessor is the one that expands the macros and substitutes the according tokens.

The macro DEFAULT_XXX() is used to initialize the structure members data_time and data by given values in its list.

The finished preprocessed code will be equivalent to:

typedef struct DEFAULT_XXX_STRUCT {
    int data_time; 
    int data;
} SomeSetting;

SomeSetting HAHASetting = { .data_time = 123, .data = 456 };

Especially why we can just .data and .data_time inside the #define?

An identifier at the left side of the . operator is redundant since the compiler according to the assignment knows what object is to be addressed.

Upvotes: 2

0___________
0___________

Reputation: 67476

#define does not know anything about the C language. It only replaces the tokens with another tokens. Simplifying it works like text substitution.

Such a macros are something I personally don't like.

your code is bad it has to look like this (see ehat I have added and what removed):

#define DEFAULT_XXX(NUM_1, NUM_2 )      \
    {                                    \
     .data_time = NUM_1,                 \
     .data = NUM_2,                      \ 
    }

typedef struct DEFAULT_XXX_STRUCT {
    int* data_time; 
    int* data;
} SomeSetting;

SomeSetting HAHASetting = DEFAULT_XXX(123,456) ;

if you compile it with the -E option (gcc) you will se the expanded code:

typedef struct DEFAULT_XXX_STRUCT {
    int* data_time;
    int* data;
} SomeSetting;

SomeSetting HAHASetting = { .data_time = 123, .data = 456, } ;

Upvotes: 1

Related Questions