我昨天发现了一些结构初始化代码,它引发了我的循环。这是一个例子:
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);
}
令人惊讶的是(对我来说),这是输出:
-> testFunc
test.first=1 test.second=2
如您所见,struct正确初始化。我不知道标签语句可以这样使用。我已经看到了其他几种进行结构初始化的方法,但是我没有在任何在线C FAQ上找到任何这种结构初始化的例子。是否有人知道这是如何/为何有效?
答案 0 :(得分:35)
以下是gcc手册的一节,它解释了结构和数组的指定初始值设定项的语法:
在结构初始值设定项中,指定要初始化的字段的名称 在元素值之前使用' .fieldname = '。例如,给定 以下结构,
struct point { int x, y; };
以下初始化
struct point p = { .y = yvalue, .x = xvalue };
相当于
struct point p = { xvalue, yvalue };
具有相同含义的另一种语法,自GCC 2.5以来已经过时,是' fieldname:',如下所示:
struct point p = { y: yvalue, x: xvalue };
可以找到相关页面here。
您的编译器应该有类似的文档。
答案 1 :(得分:33)
这些既不是标签也不是位域。
这是一种初始化可追溯到C99之前的结构成员的语法。它没有标准化,但可以在例如GCC。
typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
在C99中,标准中首次引入了初始化特定结构成员的语法,但它看起来有点不同:
typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
答案 2 :(得分:10)
是的,如上所述,这些是指定的初始值设定项,它们是标准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));
- 此外,您可以使用复合文字形式在非初始化行上使用此表单,例如:
too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};
这些都是很棒的功能,并且我能想到的每个C编译器都支持它,因为它是标准的。遗憾的是,他们并不是那么出名。
答案 3 :(得分:5)
它不是真正的“标记语句”,而是一种为结构中的命名字段赋予初始值的方法。
Gcc发出警告“使用':'过时使用指定的初始值设定项”,在C99中你应该写一下:
TEST_STRUCT test = {
.second = 2,
.first = 1
};
答案 4 :(得分:3)
C语言没有定义该语法。第6.7.8 Initialization
节说
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
如果编译器接受带冒号而没有诊断消息的指定,则表示您的编译器未符合(或未配置)符合标准。