使用标签进行C struct初始化.它有效,但如何?

And*_*ell 41 c label struct initialization

昨天我发现了一些结构初始化代码,它让我循环.这是一个例子:

typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
    TEST_STRUCT test = {
        second: 2,
        first:  1
    };
    printf("test.first=%d test.second=%d\n", test.first, test.second);
}
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是(对我来说),这是输出:

-> testFunc
test.first=1 test.second=2
Run Code Online (Sandbox Code Playgroud)

如您所见,struct正确初始化.我不知道标签语句可以这样使用.我已经看到了其他几种进行结构初始化的方法,但我没有在任何在线C FAQ上找到任何这种结构初始化的例子.有人知道这是如何/为什么有效?

sig*_*ice 39

以下是gcc手册的一节,它解释了结构和数组的指定初始值设定项的语法:

在结构初始值设定项中,指定要在元素值之前使用" .fieldname = " 初始化的字段的名称.例如,给定以下结构,

 struct point { int x, y; };
Run Code Online (Sandbox Code Playgroud)

以下初始化

 struct point p = { .y = yvalue, .x = xvalue }; 
Run Code Online (Sandbox Code Playgroud)

相当于

 struct point p = { xvalue, yvalue }; 
Run Code Online (Sandbox Code Playgroud)

另一种具有相同含义的语法,自GCC 2.5以来已经过时,是' fieldname: ',如下所示:

 struct point p = { y: yvalue, x: xvalue };
Run Code Online (Sandbox Code Playgroud)

相关页面可以在这里找到.

您的编译器应该有类似的文档.

  • 非常好,该文档清楚地解释了语法:另一种具有相同含义的语法,自GCC 2.5以来已经过时,是`fieldname:',如下所示:struct point p = {y:yvalue,x:xvalue}; (3认同)
  • @rick"fieldname:"语法是一个gcc扩展,从未成为任何ISO C标准的一部分. (3认同)

ndi*_*dim 33

这些既不是标签也不是位域.

这是一种初始化结构成员的语法,可以追溯到C99之前的日子.它不是标准化的,但可以用例如gcc.

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
Run Code Online (Sandbox Code Playgroud)

在C99中,首次在标准中引入了初始化特定结构成员的语法,但它看起来有点不同:

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
Run Code Online (Sandbox Code Playgroud)

  • @Andrew你在问题中从未说过任何关于C++的内容 (8认同)

bk.*_*bk. 12

是的,如上所述,这些是指定的初始化程序,它们是标准C,但您应该切换到使用句点而不是冒号.正如你所注意到的那样,大多数书籍在1984年左右仍然存在于语法中并且未提及它们.更有趣的事实:

- 使用指定的初始化程序时,未指定的所有内容都将初始化为零.这有助于特别大的结构,例如:

typedef struct {
   double a, b, c, d, e;
   char label[100];
} too_many_type;

too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));
Run Code Online (Sandbox Code Playgroud)

- 另外,您可以使用复合文字形式在非初始化行上使用此表单,例如:

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};
Run Code Online (Sandbox Code Playgroud)

这些都是很棒的功能,并且我能想到的每个C编译器都支持它,因为它是标准的.令人遗憾的是,他们并不是那么出名.


Tho*_*thy 5

它不是真正的"标记语句",而是一种为结构中的命名字段赋予初始值的方法.

Gcc发出警告"使用':'过时使用指定的初始化程序",而在C99中你应该写:

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };
Run Code Online (Sandbox Code Playgroud)