简体   繁体   English

用C语言评估语句

[英]Evaluation of a statement in C language

struct 
{
    int a[2], b;
} 
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

How to evaluate this line in C language? 如何用C语言评估这一行? General declaration of struct is different from this statement. 结构的一般声明与此声明不同。 Also accessing of an element in C can be done like [0].a , [0].b like this? 也可以像[0].a[0].b一样访问C中的元素?

First lines are the definition of a new structure type: 第一行是新结构类型的定义:

struct {
   int a[2], b;
}

It declares a structure with two members: an array of two int s named a and an int b . 它声明了一个包含两个成员的结构:一个名为a的两个int和一个int b的数组。

Next can be decomposed as the following, first the variable: 接下来可以分解为如下变量:

arr[]

which defines a variable arr that is an array of structures. 它定义了一个变量arr ,它是一个结构数组。 The size of the array is not defined because the variable is initialized (and so its size defined by this initialization) by: 未定义数组的大小,因为变量已初始化(因此其初始化由此初始化定义):

{ [0].a = ... }

This is a new C (C99, which not so new...) syntax to initialize contents of structured data types: designated initializer . 这是一个新的C(C99,它不是那么新......)语法来初始化结构化数据类型的内容: 指定的初始化程序

As you are initializing something the context of what you are initializing is defined (array of structure with two members). 当您初始化某些内容时,将定义您正在初始化的内容的上下文(具有两个成员的结构数组)。 Then notation [0] just references the first member of the array (so array have at least one element), and as this element is structured [0].a denotes its member a , itself an array. 然后notation [0]只引用数组的第一个成员(所以数组至少有一个元素),因为这个元素是结构化的[0].a表示它的成员a ,它本身就是一个数组。 Then this array is initialized too by { 1 } . 然后{ 1 }也初始化了这个数组。 Here the trick is that the length of this array member is already defined by the type definition: length 2, then { 1 } initializes that array with the first element equals to 1 and the second with 0 (default value for initialization of ints). 这里的技巧是这个数组成员的长度已经由类型定义定义:length 2,然后{ 1 }初始化该数组,第一个元素等于1,第二个元素为0 (初始化int的默认值)。 Etc. 等等。

At the end: 在末尾:

{[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

initializes arr as: arr初始化为:

  1. an array of length 2 一个长度为2的数组
  2. its first element member a initialized to 1,0 and its member b initialized to 1 它的第一个元素成员a初始化为1,0,其成员b初始化为1
  3. its second element member a initialized to 2,0, and its member b initialized to 2 其第二元件构件a初始化为2,0,和它的构件b初始化为2

If you use assignements then you could have write something like: 如果您使用assignements,那么您可以编写如下内容:

struct { ... } arr[2];
arr[0].a[0] = 1;
arr[0].a[1] = 0;
arr[0].b = 1;
arr[1].a[0] = 2;
arr[1].a[1] = 0;
arr[1].b = 2;

Where [0] (for example) denotes the first element of an array but needs to be prefixed with an expression that denotes that array, so arr[0] ... 其中[0] (例如)表示数组的第一个元素,但需要以表示该数组的表达式作为前缀,所以arr[0] ...

This is a declaration, not a statement, and that's why what follows the = is an initialiser, not an expression. 这是一个声明,而不是一个声明,这就是为什么在=后面的是一个初始化者,而不是一个表达式。 What you can do in an initialiser is different from what you can do in an expression. 您可以在初始化程序中执行的操作与您在表达式中可以执行的操作不同。

The syntax looks the way it does to resemble the way elements are referenced in expressions. 语法看起来像它类似于表达式中引用元素的方式。 Invalid pseudo-code to explain the meaning: 无效的伪代码来解释其含义:

struct {int a[2], b;} arr[];
arr[0].a = {1};
arr[1].a = {2};
arr[0].b = 1;
arr[1].b = 2;

The array arr is given length 2 because values for two elements are provided. 数组arr的长度为2,因为提供了两个元素的值。 arr[0] is initialised from what would traditionally be written {{1}, 1} . arr[0]从传统上写的{{1}, 1}初始化。 arr[1] is initialised from {{2}, 2} . arr[1]{{2}, 2}初始化。

Also accessing of an element in C can be done like [0].a , [0].b like this? 也可以像[0].a[0].b一样访问C中的元素?

TL;DR Only when you're writing a designated initializer . TL; DR仅在您编写指定的初始化程序时


You have two things here, a structure definition and initialization. 这里有两件事,一个结构定义和初始化。

For the initialization part, the designated initializer is used. 对于初始化部分,使用指定的初始化器。 It takes a form of 它需要一种形式

 designator: [ constant-expression ] . identifier 

So, in your case, 所以,在你的情况下,

struct 
{
    int a[2], b;
} 
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

The designated initializer instructs the compiler to create an array arr of two structure elements ( size is determined by the largest index in supplied initializer, Note 1 ) and provides the initial value of the members of those individual elements. 指定的初始化程序指示编译器创建两个结构元素的数组arr大小由提供的初始化程序中的最大索引确定,注1 )并提供这些单个元素的成员的初始值。

Thus, in your case, the largest index is 1 , so the array arr size is 2 (0-based indexing). 因此,在您的情况下,最大索引是1 ,因此数组arr大小为2(基于0的索引)。

So to speak, [0].a = {1} is trying to initialize the value of member a of element at arr[0] to 1 . 可以这么说, [0].a = {1}试图将arr[0]中元素成员a的值初始化为1 This is "equivalent" to arr[0].a[0] . 这与arr[0].a[0] “等效”。 So is for all remaining cases. 对于所有剩余的案例也是如此。

Point to note, this is not setting the values of a[0] and a[1] . 注意,这不是设置a[0]a[1] Here, due to "partial initialization" Note 2 (brace enclosed initializer does not provide initial value of all the members in the array), arr[0].a[0] is set to 1 and arr[0].a[1] is set to 0 . 这里,由于“部分初始化” 注2 (括号封闭初始化器不提供数组中所有成员的初始值), arr[0].a[0]设置为1并且arr[0].a[1]设置为0


Note 1: 注1:

Quoting C11 , chapter §6.7.9/P22 引用C11 ,章节§6.7.9/ P22

If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. 如果初始化未知大小的数组,则其大小由具有显式初始值设定项的最大索引元素确定。 The array type is completed at the end of its initializer list. 数组类型在其初始化列表的末尾完成。

Note 2: 笔记2:

Quoting C11 , chapter §6.7.9/P21 ( emphasis mine ) 引用C11 ,章节§6.7.9/ P21( 强调我的

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate , or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration. 如果括号括起的列表中的初始值设定项少于聚合的元素或成员 ,或者用于初始化已知大小的数组的字符串文字中的字符数少于数组中的元素,则聚合的其余部分应为隐式初始化与具有静态存储持续时间的对象相同。

The first part is defining a struct variable. 第一部分是定义结构变量。 Normally you see code like this: 通常你看到这样的代码:

// define the type
struct foo { ... };

// define a variable of that type
struct foo x;

But you can combine the two: 但你可以将两者结合起来:

// define a type and a variable of that type
struct foo { ... } x;

In the latter case you don't even have to name the type: 在后一种情况下,您甚至不必命名类型:

// define a variable of an unnamed struct type
struct { ... } x;

In your case we have struct { int a[2], b; } 在你的例子中,我们有struct { int a[2], b; } struct { int a[2], b; } , so we're dealing with an unnamed struct with two members, an array of 2 ints called a and an int called b . struct { int a[2], b; } ,所以我们处理与两名成员一名不愿透露姓名结构,2个整数数组称为a和一个int叫做b

The variable we're declaring is arr . 我们宣布的变量是arr The [] after the name mean that we're defining it as an array. 名称后面的[]表示我们将其定义为数组。

Usually we see something like: 通常我们看到类似的东西:

// define an array of 2 elements
int arr[2];

We can add an initializer: 我们可以添加一个初始化器:

// define and initialize an array of 2 elements
int arr[2] = { 100, 200 };

With an initializer we don't have to say explicitly how big the array is; 使用初始化程序,我们不必明确说明数组有多大; it follows from the initializer: 它来自初始化器:

// define and initialize an array of 2 elements
int arr[] = { 100, 200 };

Applying this to your case, you might expect to see something like: 将此应用于您的案例,您可能会看到以下内容:

struct { int a[2], b; } arr[] = { { {1}, 1 }, { {2}, 2 } };
//                                  ^a^         ^a^
//                                ^^struct^^  ^^struct^^ 

The braces get a bit crazy because we have an array ( int a[2] ) nested inside a struct nested inside an array ( arr[] ). 大括号有点疯狂,因为我们有一个嵌套在数组( arr[] )内的结构中的数组( int a[2] arr[] )。 If you're wondering what happened to the second elements of the a s: When a variable is only partially initialized, all remaining parts are set to 0 . 如果你想知道a的第二个元素发生了什么:当一个变量只是部分初始化时,所有剩余的部分都设置为0 So this code really initializes the inner arrays as {1, 0} and {2, 0} . 所以这段代码确实将内部数组初始化为{1, 0}{2, 0}

The initializer in your actual code looks a bit different. 实际代码中的初始化程序看起来有点不同。 It uses a feature introduced in C99, called "designated initializers". 它使用C99中引入的一个功能,称为“指定初始化器”。 With a normal initializer you have to list the values in order; 使用普通的初始化程序,您必须按顺序列出值; in C99 you can prepend a "designator" that says where the value goes. 在C99中,您可以添加一个“指示符”,指出值的位置。 The designator can be either an array index in brackets ( [ ] ) or a . 指示符可以是括号( [ ] )或a中的数组索引. followed by a member name. 后跟成员名称。 Designators can also be chained: [0].b = 42 means "initialize member b of element 0 of this array to 42". 指示符也可以链接: [0].b = 42表示“将此数组的元素0的成员b初始化为42”。

That's what's going on here: 这就是这里发生的事情:

struct { int a[2], b; } arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

If we reorder the initializer by index, we get: 如果我们按索引重新排序初始化程序,我们得到:

struct { int a[2], b; } arr[] = {[0].a = {1}, [0].b = 1, [1].a = {2}, [1].b = 2};

We can then merge adjacent designators: 然后我们可以合并相邻的指示符:

struct { int a[2], b; } arr[] = {[0] = { .a = {1}, .b = 1 }, [1] = {.a = {2}, .b = 2} };

This makes it a bit easier to see that we're initializing two elements (so arr has size 2) and what the values actually are. 这使我们更容易看到我们正在初始化两个元素(因此arr大小为2)以及实际值是什么。

All of these forms are equivalent to: 所有这些形式都相当于:

struct { int a[2], b; } arr[] = { { {1}, 1 }, { {2}, 2 } };

You have declaring array of struct and [0].a , [0].b is a C99 syntax. 你已经声明了struct的数组和[0].a[0].b是一个C99语法。

The [index] and .fieldname designators before an = to specify a nested subobject to initialize, the list is taken relative to the subobject corresponding to the closest surrounding brace pair. =之前的[index].fieldname指示符指定要初始化的嵌套子对象,该列表是相对于与最近的周围括号对对应的子对象获取的。

refer this link . 请参阅此链接

the posted code has some incorrect initialization syntax. 发布的代码有一些不正确的初始化语法。

I used the gcc compiler on ubuntu linux 16.04 我在ubuntu linux 16.04上使用了gcc编译器

the compiler output the following messages: 编译器输出以下消息:

warning: missing initializer for field 'b' of 'struct <anonymous>' [-Wmissing-field-initializers]
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

note: 'b' declared here
int a[2], b;

the above lines are repeated twice. 以上几行重复两次。

please correct the syntax and repost 请更正语法并重新发布

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM