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 中的声明有两个主要部分 -声明说明符序列(可能包括存储类说明符static和auto,类型说明符,如,,,,int类型限定符,等)和可选的声明符序列(基本上,变量或函数名),每个都可以被初始化。例如,在声明中doublecharstruct fooconst
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两种形式——一种是你指定结构的内容,另一种是你不指定。
identifier是结构或联合的标记名称;这是您稍后可以引用该特定类型的方式(作为另一个声明的一部分或sizeof表达式的一部分等)。
请注意,在第一种情况下,您指定结构类型的成员,标签名称是可选的 - 编写如下声明是完全合法的
struct { int a; int b; } x;
| | |
+---------+------------+ |
| V
V declarator
type-specifier
结构定义本身是一个类型说明符,就像intordouble等一样。
但是,如果没有标记名称,则不能在以后的声明中引用相同的结构类型。您当然可以重复另一个变量的定义:
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 声明语法,尤其是关于结构、联合和枚举的声明语法相当灵活,并且您书中列出的所有方法都同样有效。