簡體   English   中英

C:無法理解這種類型的結構和變量聲明的第二種和第三種方法如何有效?

[英]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 2011在線草案,6.7

可愛。 這是什么意思?

基本上,C語言中的聲明有兩個主要部分:一系列聲明說明符 (可能包括諸如staticauto類的存儲類說明符,諸如intdoublecharstruct 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定義本身就是類型說明符,就像intdouble一樣。

但是,如果沒有標簽名稱,則無法在以后的聲明中引用此相同的結構類型。 您當然可以為另一個變量重復定義:

struct { int a; int b; } y;

但是xy的類型是不同的 -編譯器認為每個struct定義都是不同的類型,即使它們的內容相同。

現在,請記住上面的通用聲明語法,聲明中的聲明符列表是可選的 這就是我們可以只聲明標記名稱的結構的方法(盡管根據上述約束,如果您未聲明此類型的變量,則必須包括標記名稱):


struct foo { int a; int b; };
|                          |
+-----------+--------------+
            |
            V
      type-specifier

我們已經定義了結構類型,並為其賦予了標簽名稱foo 我們可以將這種類型的對象聲明為

struct foo x;
struct foo y;

因為從上面的語法來看:

struct foo x;
|        |
+---+----+
    |
    V
type-specifier

這次, xy被認為是同一類型。

我們還可以在定義結構的同時聲明一個變量:

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.

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