【问题标题】:Using define macro to initialize structure object in C使用define宏在C中初始化结构对象
【发布时间】:2020-10-03 05:27:26
【问题描述】:
#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) ;

我想问为什么这种定义可以初始化“HAHASetting”对象。 特别是为什么我们可以在#define 中只使用 .data 和 .data_time?

【问题讨论】:

  • #define 通过文本替换改变编译器看到的内容。
  • 它是如何知道 .是为了结构的数据成员吗?我记得我们先从右侧运行。
  • @SamLi 它没有。正如 Karl 所说,这只是文本替换。
  • 考虑替换文本后代码的样子。如果你不明白,你可以用那个替换的文本问另一个问题;我猜这是重复的,但至少你得到了你需要的答案。

标签: c struct macros initialization c-preprocessor


【解决方案1】:

首先,提供的代码有问题。我猜它看起来像这样,从你得到它的地方:

#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. 请注意,在属于#define 宏的每一行之后需要有一个\,除了最后一行以; 结尾。 \ 具有编译器将考虑宏的下一行的效果。

    如果您忽略将\ 放置在宏的另一部分在另一行之后的行中,这将是一个语法错误,编译器会在尝试编译时很快提示您。

    没有all \'s 你需要将整个宏写在一行中,比如:

    #define DEFAULT_XXX( NUM_1, NUM_2 ) { .data_time = NUM_1, .data = NUM_2 };
    
  2. DEFAULT_XXX 后面需要跟它的列表( NUM_1, NUM_2 ) 之间没有空格。

  3. 结构成员data_time 和data 都是指向int 的类型指针,但传递的值是int 类型。存在类型不匹配。这是 C 语法违规。如果应该为它们分配int 值,它们应该是int 类型,而不是int *。

    查看这个问题了解更多信息:

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


例子:

#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);
}

输出:

123
456

我想问为什么这种#define可以初始化(ialize)"HAHASetting"对象?

#define 宏基本上用于替换文本,充当函数或用作本示例中提供的初始化程序(可能还有其他用途,但现在涵盖所有内容太多了,与回答您的问题无关好吧)。 C 预处理器是扩展宏并替换相应标记的预处理器。

宏 DEFAULT_XXX() 用于通过其列表中的给定值初始化结构成员 data_time 和 data。

完成的预处理代码将相当于:

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

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

尤其是为什么我们可以只在#define 中使用.data 和.data_time?

. 运算符左侧的标识符是多余的,因为编译器根据分配知道要寻址的对象。

【讨论】:

    【解决方案2】:

    #define 对 C 语言一无所知。它仅用另一个令牌替换令牌。简化它就像文本替换一样。

    这样的宏是我个人不喜欢的。

    您的代码很糟糕,它必须看起来像这样(请参阅我添加的 ehat 和删除的内容):

    #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) ;
    

    如果您使用 -E 选项 (gcc) 编译它,您将看到扩展代码:

    typedef struct DEFAULT_XXX_STRUCT {
        int* data_time;
        int* data;
    } SomeSetting;
    
    SomeSetting HAHASetting = { .data_time = 123, .data = 456, } ;
    

    【讨论】:

    • 所以我在这里替换了这个东西:{ .data_time = NUM​​_1, .data = NUM​​_2, } 像 MIL?
    • “MIL”是什么意思?
    • @KarlKnechtel 我猜 OP 的意思是 C++ 术语“成员初始化列表”。
    • 是的,成员初始化列表。我的第一个 prog lang 是 C++,我猜 C 会有相同的术语。
    猜你喜欢
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多