31

这是我刚刚在别人的问题中找到的初始化。

my_data data[]={
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

我以前从未见过这样的东西,也找不到解释 .name 如何可能是正确的。
我正在寻找的是这个过程是如何一步一步地进行的。

看起来它得到了:

  1. data;
  2. *data;
  3. (*data).name;
  4. (*data).name="Peter";

还是我完全错了?

4

6 回答 6

35

my_data是一个name作为字段data[]的结构并且是结构的数组,您正在初始化每个索引。阅读以下内容:

5.20 指定初始化器

在结构初始化器中,.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 };

你也可以写:

my_data data[] = {
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

作为:

my_data data[] = {
    [0] = { .name = "Peter" },
    [1] = { .name = "James" },
    [2] = { .name = "John" },
    [3] = { .name = "Mike" }
}; 

或者:

my_data data[] = {
    [0].name = "Peter",
    [1].name = "James",
    [2].name = "John",
    [3].name = "Mike"
}; 

第二种和第三种形式可能很方便,因为您不需要按顺序编写,例如,上述所有示例都等效于:

my_data data[] = {
    [3].name = "Mike",
    [1].name = "James",
    [0].name = "Peter",
    [2].name = "John"
}; 

如果您的结构中有多个字段(例如,一个int age),您可以使用以下命令一次初始化所有字段:

my_data data[] = {
    [3].name = "Mike",
    [2].age = 40,
    [1].name = "James",
    [3].age = 23,
    [0].name = "Peter",
    [2].name = "John"
}; 

要了解数组初始化,请阅读奇怪的初始化表达式?

此外,您可能还想阅读@Shafik Yaghmour对 switch case 的回答:What is "..." in switch-case in C code

于 2013-09-20T16:36:31.943 回答
30

这里只有两种语法在起作用。

  1. 普通的旧数组初始化:

    int x[] = {0, 0}; // x[0] = 0, x[1] = 0
    
  2. 一个指定的初始化器。请参阅此问题的公认答案:如何根据 C 编程语言标准初始化结构

    不过,语法是不言自明的。你可以这样初始化:

    struct X {
        int a;
        int b;
    }
    struct X foo = { 0, 1 }; // a = 0, b = 1
    

    或使用任何排序,

    struct X foo = { .b = 0, .a = 1 }; // a = 1, b = 0
    
于 2013-09-20T16:35:31.673 回答
22

这里没有“一步一步”。当使用常量表达式执行初始化时,该过程本质上是在编译时执行的。当然,如果数组被声明为本地对象,它会在本地分配并在运行时初始化,但这仍然可以被认为是一个无法有意义细分的单步过程。

指定初始化器允许您为结构对象的特定成员(或数组的特定元素)提供初始化器。所有其他成员都进行零初始化。因此,如果my_data声明为

typedef struct my_data {
  int a;
  const char *name;
  double x;
} my_data;

那么你的

my_data data[]={
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

只是一种更紧凑的形式

my_data data[4]={
    { 0, "Peter", 0 },
    { 0, "James", 0 },
    { 0, "John", 0 },
    { 0, "Mike", 0 }
};

我希望你知道后者是做什么的。

于 2013-09-20T16:46:13.633 回答
2

它被称为C99 中引入的指定初始化程序。它用于初始化struct或数组,在本例中,struct.

给定

struct point { 
    int x, y;
};

以下初始化

struct point p = { .y = 2, .x = 1 };

相当于C89风格

struct point p = { 1, 2 };
于 2013-09-20T16:34:27.647 回答
1

这很简单: my_data是一个之前定义的结构类型。所以你想声明my_data一些元素的-array,就像你会做的那样

char a[] = { 'a', 'b', 'c', 'd' };

所以数组将有 4 个元素,你将它们初始化为

a[0] = 'a', a[1] = 'b', a[1] = 'c', a[1] ='d';

这称为指定初始化程序(我没记错)。

它只是表明数据必须是类型my_dat,并且必须是一个数组,该数组需要存储如此多的 my_data 结构,以至于每个类型成员名称为 Peter、James、John 和 Mike。

于 2013-09-20T16:33:06.827 回答
1

它是一个指定的初始化器,由 C99 标准引入;它允许您按名称初始化结构或联合对象的特定成员。 my_data显然是具有类型orstruct成员name的类型的 typedef 。 char *char [N]

于 2013-09-20T16:34:47.103 回答