struct {int a[2];} arr[] = {{1},{2}};
请简化上面的代码,特别是arr[] = {{1},{2}};
部分及其与结构的关系。
p.s。:-arr[] = {{1},{2}}
的初始化似乎是2d array
,但是对1d array(arr[])
进行了左值分配。同样,如果我们调用a[2]
,arr[].a[2]
将保持什么状态。
struct {int a[2];} arr[] = {{1},{2}};
请简化上面的代码,特别是arr[] = {{1},{2}};
部分及其与结构的关系。
p.s。:-arr[] = {{1},{2}}
的初始化似乎是2d array
,但是对1d array(arr[])
进行了左值分配。同样,如果我们调用a[2]
,arr[].a[2]
将保持什么状态。
struct {int a[2];} arr[] = {{1},{2}};
上述初始化目前尚未完成,您应该看到以下警告
warning: (near initialization for ‘arr[0].a’)
正确的初始化是
struct {int a[2];} arr[] = {1.
{ { {1} },{ {2} }}
---
|
--------------> is for int arr[0].a[0] // in this case arr[0].a[1] will be not be initialized
2
{ { {1} },{ {2} }}
------- ------
| |
| ----> is for arr[1]
--------------> is for arr[0]
3
{ { {1} },{ {2} }}
--------------------
|
------------------> is for complete arr[]
,{{2}}};
input$myDatatable_cells_selected
,
简化
struct {int a[2];} arr[] = {{1},{2}};
struct quux {
int a[2];
};
struct quux arr[2];
arr[0].a[0] = 1;
arr[0].a[1] = 0;
arr[1].a[0] = 2;
arr[1].a[1] = 0;
,
首先,让我们掌握聚合(数组或结构)初始化的规则。 C17 standard draft在6.7.9,初始化中说:
17 每个用大括号括起来的初始化器列表都有一个关联的当前对象。不存在任何指定时,将初始化当前对象的 subobjects 为了[...]。
因此,初始化器列表还会初始化子对象(即使没有内部花括号)。
最外面的括号对中的当前对象是arr
,即结构数组。内括号对内的当前对象是数组arr[i]
的元素。 arr
的初始化器列表中有两个子初始化器列表,其中arr
的元素数为2。
内部初始化程序列出{1}
。 {2}
用于分别初始化一个未命名的结构。每个结构arr[i]
依次包含一个聚合,即成员数组a
,因此以下规则很重要:
如果聚合或并集包含作为聚合的元素或成员[...],则这些规则递归适用于 。
arr[0]
中的结构的初始值设定项列表为{1}
,因此,单独元素1
用于初始化其元素。唯一的元素是a
,它是2个整数的数组。由于有递归规则,因此1用于按顺序初始化此子聚合。因为所有arr[0],the second int element in
a都只有一个初始化器,所以没有匹配的初始化器。在这里,以下规则起作用:
19 [...]所有未明确初始化的子对象应隐式初始化为与具有静态存储持续时间的对象相同。
静态对象被零初始化(6.7.9 / 10)。
相同的理由适用于arr
中的第二个元素。
这样,我们最终得到一个arr
,其中包含两个元素,每个元素都是一个未命名的结构,该结构包含2个int数组,其中第一个用给定值初始化,第二个隐式初始化零。
让我们按照这些规则进行一些操作。例如,我们可以不提供初始化器,该初始化器将自动变量的所有成员/元素零初始化。 (在这些情况下,我有多少次见过人们记忆障碍!)
struct jumble { int i; char *p; float f; };
void f() { struct jumble arr[10] = {}; /* zero numbers,nullpointer */ }
以您的示例为基础:
#include<stdio.h>
struct int2T { int a[2]; };
void printStructArr(const char *name,struct int2T *arr,size_t numElems)
{
for(int arri=0; arri<numElems; arri++)
{
for(int ai=0; ai < sizeof(arr[arri].a)/sizeof(*arr[arri].a); ai++)
{ fputs(name,stdout);
printf("[%d].a[%d]: %d\n",arri,ai,arr[arri].a[ai]);
}
}
printf("\n");
}
int main()
{
struct int2T arr1[] = {{1},{2}};
// equivalent: Proper bracing
struct int2T arr1b[] = { // arr array of structs
{ // arr[0] single struct
{ // arr[0].a member array within struct
1,// arr[0].a[0] int
0 // arr[0].a[1] int
}
},{ // arr[1] single struct
{ // arr[1].a member array within struct
2,// arr[1].a[0] int
0 // arr[1].a[1] int
}
}
};
struct int2T arr2[] = { // arr,array of structs
11,// trying to initialize arr[0]
// -> recursing: trying to initialize arr[0].a
// -> recursing: trying to initialize arr[0].a[0]. Success!
12 }; // same as above.
struct int2T arr3[] = {
21,// trying to initialize arr[0]
// -> recursing: trying to initialize arr[0].a
// -> recursing: trying to initialize arr[0].a[0]. Success!
22,// next element in array,initialize arr[0].a[1]. Success!
23 // elements in inner array "a" exhausted,unwind recursion
// trying to continue initializing arr[0]. No more members to initialize,// unwinding recursion to next upper level.
// trying to initialize next element in array "arr",arr[1]
// -> recursing: trying to initialize arr[1].a
// -> recursing: trying to initialize arr[1].a[0]. Success!
// no more initializer left for arr[1].a[1]
// -> Zero-initialize arr[1].a[1],then unwind.
// Continuing initialization of arr[1]: No more members,unwind
// Continuing initialization of arr: No more initializers left,stop.
};
printStructArr("arr1",arr1,sizeof(arr1)/sizeof(*arr1));
printStructArr("arr1b",arr1b,sizeof(arr1b)/sizeof(*arr1b));
printStructArr("arr2",arr2,sizeof(arr2)/sizeof(*arr2));
printStructArr("arr3",arr3,sizeof(arr3)/sizeof(*arr3));
return 0;
}
输出:
arr1[0].a[0]: 1
arr1[0].a[1]: 0
arr1[1].a[0]: 2
arr1[1].a[1]: 0
arr1b[0].a[0]: 1
arr1b[0].a[1]: 0
arr1b[1].a[0]: 2
arr1b[1].a[1]: 0
arr2[0].a[0]: 11
arr2[0].a[1]: 12
arr3[0].a[0]: 21
arr3[0].a[1]: 22
arr3[1].a[0]: 23
arr3[1].a[1]: 0