[英]C : Can't understand how 2nd and 3rd method of declaration of structure and variables of this type are valid?
這是我書中給出的三種方法:
1)
struct book
{ char name;
float price;
int pages;
};
struct book b1; b2; b3;
2)
struct book
{
char name;
float price;
int pages;
}
b1, b2, b3;
3)
struct
{
char name;
float price;
int pages;
} b1, b2, b3;
在第二種方法中,為什么在結構類型聲明中的右花括號后不加分號有一個困惑?
第三種方法對我來說沒有任何意義,因為我們甚至都沒有聲明結構的名稱。
那么,這兩種方法如何有效?
在定義struct
,您還可以定義該結構的一個或多個實例。 這是第二個和第三個示例中發生的情況。
兩者之間的區別在於,一個在定義類型時就聲明了struct book
類型的三個變量,而另一個聲明了三個類型為匿名struct的變量。 在后一種情況下,這意味着無法定義該類型的其他變量,因為該結構沒有名稱並且沒有關聯的typedef
。
整個結構
struct {
int field1;
char field2;
// ...
}
本身就是一種類型 。 因此,您可以像使用其他類型一樣在變量聲明中使用它。 它們都是形式
<type> <identifier>;
以及可選的更多標識符,以一次聲明多個變量。
例如:
struct {int x; char y;} bar;
是有效的變量聲明,就像
int bar;
是。 請記住,換行符在C中沒有任何語法含義。
使用struct
,您可以為其命名(稱為struct tag ),如下所示:
struct foo {
int field1;
char field2;
// ...
};
如果這樣做,以后可以通過編寫以下命令使用相同的結構類型
struct foo
而不是重復所有字段。 實際上,這是最常見的用法。
TL / DR-C聲明語法允許所有這三種方法 。
有耐心,這需要一段時間。
讓我們從聲明的語法開始:
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declaration
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
opt
下標表示該項目是可選的; IOW,聲明說明符的序列可以接着說明符(或不)的序列,一個類型說明之后可以進行更聲明說明符(或不)等。
我們還有以下約束 :
除static_assert聲明以外的其他聲明應至少聲明一個聲明符(函數的參數或結構或聯合的成員除外),標記或枚舉的成員。
可愛。 這是什么意思?
基本上,C語言中的聲明有兩個主要部分:一系列聲明說明符 (可能包括諸如static
和auto
類的存儲類說明符,諸如int
, double
, char
, struct foo
類的類型說明符,諸如const
等之類的類型限定符)和一個聲明符的可選序列(基本上是變量名或函數名),每個聲明符均可初始化。 例如,在聲明中
static const int *foo[N] = { &bar, &blah, ... };
我們的聲明說明符是static const int
,我們的聲明符 *foo[N]
我們的初始化是{ &bar, &blah, ... }
對於您的問題,我們感興趣的是type-specifier
,特別是struct-or-union-specifier
:
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
atomic-type-specifier
struct-or-union-specifier
enum-specifier
typedef-name
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
struct-or-union-specifier
有兩種形式-一種用於指定struct的內容,另一種則不指定。
identifier
是結構或聯合的標簽名稱 ; 這是稍后您可以引用該特定類型的方式(作為另一個聲明的一部分,或sizeof
表達式的一部分,等等)。
請注意,在第一種情況下,當您指定結構類型的成員時,標記名稱是可選的-編寫這樣的聲明是完全合法的
struct { int a; int b; } x;
| | |
+---------+------------+ |
| V
V declarator
type-specifier
struct定義本身就是類型說明符,就像int
或double
一樣。
但是,如果沒有標簽名稱,則無法在以后的聲明中引用此相同的結構類型。 您當然可以為另一個變量重復定義:
struct { int a; int b; } y;
但是x
和y
的類型是不同的 -編譯器認為每個struct
定義都是不同的類型,即使它們的內容相同。
現在,請記住上面的通用聲明語法,聲明中的聲明符列表是可選的 。 這就是我們可以只聲明標記名稱的結構的方法(盡管根據上述約束,如果您未聲明此類型的變量,則必須包括標記名稱):
struct foo { int a; int b; };
| |
+-----------+--------------+
|
V
type-specifier
我們已經定義了結構類型,並為其賦予了標簽名稱foo
; 我們可以將這種類型的對象聲明為
struct foo x;
struct foo y;
因為從上面的語法來看:
struct foo x;
| |
+---+----+
|
V
type-specifier
這次, x
和y
被認為是同一類型。
我們還可以在定義結構的同時聲明一個變量:
struct foo { int a; int b; } x; | | +----------+---------------+ | V type-specifier
struct foo y; | | +----+---+ | V type-specifier
第一個聲明創建struct foo
類型,並將x
聲明為該類型的變量。 第二個聲明使用先前定義的struct foo
類型來聲明變量y
。
基本上,C聲明語法(尤其是在結構,聯合和枚舉方面)非常靈活,並且書中列出的所有方法均同等有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.