簡體   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};

如何用C語言評估這一行? 結構的一般聲明與此聲明不同。 也可以像[0].a[0].b一樣訪問C中的元素?

第一行是新結構類型的定義:

struct {
   int a[2], b;
}

它聲明了一個包含兩個成員的結構:一個名為a的兩個int和一個int b的數組。

接下來可以分解為如下變量:

arr[]

它定義了一個變量arr ,它是一個結構數組。 未定義數組的大小,因為變量已初始化(因此其初始化由此初始化定義):

{ [0].a = ... }

這是一個新的C(C99,它不是那么新......)語法來初始化結構化數據類型的內容: 指定的初始化程序

當您初始化某些內容時,將定義您正在初始化的內容的上下文(具有兩個成員的結構數組)。 然后notation [0]只引用數組的第一個成員(所以數組至少有一個元素),因為這個元素是結構化的[0].a表示它的成員a ,它本身就是一個數組。 然后{ 1 }也初始化了這個數組。 這里的技巧是這個數組成員的長度已經由類型定義定義:length 2,然后{ 1 }初始化該數組,第一個元素等於1,第二個元素為0 (初始化int的默認值)。 等等。

在末尾:

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

arr初始化為:

  1. 一個長度為2的數組
  2. 它的第一個元素成員a初始化為1,0,其成員b初始化為1
  3. 其第二元件構件a初始化為2,0,和它的構件b初始化為2

如果您使用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;

其中[0] (例如)表示數組的第一個元素,但需要以表示該數組的表達式作為前綴,所以arr[0] ...

這是一個聲明,而不是一個聲明,這就是為什么在=后面的是一個初始化者,而不是一個表達式。 您可以在初始化程序中執行的操作與您在表達式中可以執行的操作不同。

語法看起來像它類似於表達式中引用元素的方式。 無效的偽代碼來解釋其含義:

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

數組arr的長度為2,因為提供了兩個元素的值。 arr[0]從傳統上寫的{{1}, 1}初始化。 arr[1]{{2}, 2}初始化。

也可以像[0].a[0].b一樣訪問C中的元素?

TL; DR僅在您編寫指定的初始化程序時


這里有兩件事,一個結構定義和初始化。

對於初始化部分,使用指定的初始化器。 它需要一種形式

 designator: [ constant-expression ] . identifier 

所以,在你的情況下,

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

指定的初始化程序指示編譯器創建兩個結構元素的數組arr大小由提供的初始化程序中的最大索引確定,注1 )並提供這些單個元素的成員的初始值。

因此,在您的情況下,最大索引是1 ,因此數組arr大小為2(基於0的索引)。

可以這么說, [0].a = {1}試圖將arr[0]中元素成員a的值初始化為1 這與arr[0].a[0] “等效”。 對於所有剩余的案例也是如此。

注意,這不是設置a[0]a[1] 這里,由於“部分初始化” 注2 (括號封閉初始化器不提供數組中所有成員的初始值), arr[0].a[0]設置為1並且arr[0].a[1]設置為0


注1:

引用C11 ,章節§6.7.9/ P22

如果初始化未知大小的數組,則其大小由具有顯式初始值設定項的最大索引元素確定。 數組類型在其初始化列表的末尾完成。

筆記2:

引用C11 ,章節§6.7.9/ P21( 強調我的

如果括號括起的列表中的初始值設定項少於聚合的元素或成員 ,或者用於初始化已知大小的數組的字符串文字中的字符數少於數組中的元素,則聚合的其余部分應為隱式初始化與具有靜態存儲持續時間的對象相同。

第一部分是定義結構變量。 通常你看到這樣的代碼:

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

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

但你可以將兩者結合起來:

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

在后一種情況下,您甚至不必命名類型:

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

在你的例子中,我們有struct { int a[2], b; } struct { int a[2], b; } ,所以我們處理與兩名成員一名不願透露姓名結構,2個整數數組稱為a和一個int叫做b

我們宣布的變量是arr 名稱后面的[]表示我們將其定義為數組。

通常我們看到類似的東西:

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

我們可以添加一個初始化器:

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

使用初始化程序,我們不必明確說明數組有多大; 它來自初始化器:

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

將此應用於您的案例,您可能會看到以下內容:

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

大括號有點瘋狂,因為我們有一個嵌套在數組( arr[] )內的結構中的數組( int a[2] arr[] )。 如果你想知道a的第二個元素發生了什么:當一個變量只是部分初始化時,所有剩余的部分都設置為0 所以這段代碼確實將內部數組初始化為{1, 0}{2, 0}

實際代碼中的初始化程序看起來有點不同。 它使用C99中引入的一個功能,稱為“指定初始化器”。 使用普通的初始化程序,您必須按順序列出值; 在C99中,您可以添加一個“指示符”,指出值的位置。 指示符可以是括號( [ ] )或a中的數組索引. 后跟成員名稱。 指示符也可以鏈接: [0].b = 42表示“將此數組的元素0的成員b初始化為42”。

這就是這里發生的事情:

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

如果我們按索引重新排序初始化程序,我們得到:

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

然后我們可以合並相鄰的指示符:

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

這使我們更容易看到我們正在初始化兩個元素(因此arr大小為2)以及實際值是什么。

所有這些形式都相當於:

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

你已經聲明了struct的數組和[0].a[0].b是一個C99語法。

=之前的[index].fieldname指示符指定要初始化的嵌套子對象,該列表是相對於與最近的周圍括號對對應的子對象獲取的。

請參閱此鏈接

發布的代碼有一些不正確的初始化語法。

我在ubuntu linux 16.04上使用了gcc編譯器

編譯器輸出以下消息:

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;

以上幾行重復兩次。

請更正語法並重新發布

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM