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

时间:2022-09-06 11:23:13

I found some struct initialization code yesterday that threw me for a loop. Here's an example:

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

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

Surprisingly (to me), here's the output:

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

-> testFunc
test.first=1 test.second=2

As you can see, the struct gets initialized properly. I wasn't aware labeled statements could be used like that. I've seen several other ways of doing struct initialization, but I didn't find any examples of this sort of struct initialization on any of the online C FAQs. Is anybody aware of how/why this works?

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

5 个解决方案

#1


31  

Here is the section of the gcc manual which explains the syntax of designated initializers for both structs and arrays:

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

In a structure initializer, specify the name of a field to initialize with '.fieldname =' before the element value. For example, given the following structure,

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

 struct point { int x, y; };

the following initialization

以下初始化

 struct point p = { .y = yvalue, .x = xvalue }; 

is equivalent to

相当于

 struct point p = { xvalue, yvalue }; 

Another syntax which has the same meaning, obsolete since GCC 2.5, is 'fieldname:', as shown here:

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

 struct point p = { y: yvalue, x: xvalue };

The relevant page can be found here.

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

Your compiler should have similar documentation.

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

#2


32  

These are neither labels nor bitfields.

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

This is a syntax to initialize struct members dating back to the days before C99. It is not standardized but available in e.g. gcc.

这是一种初始化可追溯到C99之前的结构成员的语法。它没有标准化,但可以在例如GCC。

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };

In C99, syntax for initializing specific struct members has been introduced for the first time in a standard, but it looks a little differently:

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

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };

#3


9  

Yes, as pointed out above, these are designated initializers, which are standard C, though you should switch to using periods instead of colons. And as you note, most of the books out there are still stuck somewhere around 1984 in their syntax and fail to mention them. More fun facts:

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

--When using designated initializers, everything not specified is initialized at zero. This helps with exceptionally large structs, e.g.:

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

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

--Also, you can use the compound literal form to use this form on a non-initialization line, e.g.:

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

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

These are really great features, and are supported by every C compiler that I can think of, being that it's the standard. It's a shame that they're not so well known.

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

#4


5  

It's not really "labeled statements", but a way to give initial values to the named fields in the struct.

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

Gcc gives a warning about "obsolete use of designated initializer with ':'", and in C99 you should instead write:

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

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

#5


3  

That syntax is not defined by the C Standard. Section 6.7.8 Initialization says

该语法不是由C标准定义的。第6.7.8节初始化说

         designation:
                designator-list =
         designator-list:
                designator
                designator-list designator
         designator:
                [ constant-expression ]
                . identifier

If your compiler accepts a designation with a colon without a diagnostic message it means your compiler is not (or is configured not to be) Standards compliant.

如果编译器接受带冒号而没有诊断消息的指定,则表示您的编译器未符合(或未配置)符合标准。

#1


31  

Here is the section of the gcc manual which explains the syntax of designated initializers for both structs and arrays:

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

In a structure initializer, specify the name of a field to initialize with '.fieldname =' before the element value. For example, given the following structure,

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

 struct point { int x, y; };

the following initialization

以下初始化

 struct point p = { .y = yvalue, .x = xvalue }; 

is equivalent to

相当于

 struct point p = { xvalue, yvalue }; 

Another syntax which has the same meaning, obsolete since GCC 2.5, is 'fieldname:', as shown here:

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

 struct point p = { y: yvalue, x: xvalue };

The relevant page can be found here.

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

Your compiler should have similar documentation.

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

#2


32  

These are neither labels nor bitfields.

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

This is a syntax to initialize struct members dating back to the days before C99. It is not standardized but available in e.g. gcc.

这是一种初始化可追溯到C99之前的结构成员的语法。它没有标准化,但可以在例如GCC。

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };

In C99, syntax for initializing specific struct members has been introduced for the first time in a standard, but it looks a little differently:

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

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };

#3


9  

Yes, as pointed out above, these are designated initializers, which are standard C, though you should switch to using periods instead of colons. And as you note, most of the books out there are still stuck somewhere around 1984 in their syntax and fail to mention them. More fun facts:

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

--When using designated initializers, everything not specified is initialized at zero. This helps with exceptionally large structs, e.g.:

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

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

--Also, you can use the compound literal form to use this form on a non-initialization line, e.g.:

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

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

These are really great features, and are supported by every C compiler that I can think of, being that it's the standard. It's a shame that they're not so well known.

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

#4


5  

It's not really "labeled statements", but a way to give initial values to the named fields in the struct.

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

Gcc gives a warning about "obsolete use of designated initializer with ':'", and in C99 you should instead write:

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

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

#5


3  

That syntax is not defined by the C Standard. Section 6.7.8 Initialization says

该语法不是由C标准定义的。第6.7.8节初始化说

         designation:
                designator-list =
         designator-list:
                designator
                designator-list designator
         designator:
                [ constant-expression ]
                . identifier

If your compiler accepts a designation with a colon without a diagnostic message it means your compiler is not (or is configured not to be) Standards compliant.

如果编译器接受带冒号而没有诊断消息的指定,则表示您的编译器未符合(或未配置)符合标准。