如果初始化一个具有静态存储时期(比如静态外部链接、静态内部链接或静态空链接)的变量,只能使用常量值。这条规则同样也适用于结构。如果初始化一个具有静态存储时期的结构,初始化项目列表中的值必须是常量表达式。如果存储时期是自动的,列表中的值就不必是常量了。
声明结构的过程和定义结构变量的过程可以被合并成一步。如下所示,将声明和变量定义合并在一起,是不需要使用标记的一种情况。
struct
{
char title[MAXTITL];
char author[MAXAUTL];
float value;
} library;
然而,如果您想多次使用一个结构模板,就需要使用带有标记的形式;或者您也可以使用本章后面部分将要讲到的typedef。
在一些早期的C实现中,结构不能作为参数被传递给函数,但指向结构的指针可以。
和数组不同, 一个结构的名字不是结构的地址,必须使用&运算符。
如果him是指向名为barney的guy类型结构的指针,则下列表达式是等价的:
barney.income == (*him).income == him->income //假设him == &barney
现在C允许把一个结构赋值给另一个结构。也就是说,如果n_data和o_data是同一类型的结构,可以像下面这样做:
o_data = n_data; // o_data中即使包含数组成员, o_data初始化中,或者后续赋值都合法
结构不仅可以作为参数传递给函数,也可以作为函数返回值返回。
出现在所有函数外面的复合文字具有静态存储时期,而出现在一个代码块内部的复合文字具有自动存储时期。适用于常规初始化项目列表的语法规则同样也适用于复合文字。这意味着,例如,可以在复合文字中使用指定初始化项目。
伸缩型数组成员: c99具有一个称为伸缩型数组成员(flexible array member)的新特性。利用这一新特性可以声明最后一个成员是一个具有特殊属性的数组的结构。该数组成员的特殊属性之一是它不存在,至少不立即存在。第二个特殊属性是您可以编写适当的代码使用这个伸缩型数组成员,就像它确实存在并且拥有您需要的任何数目的元素一样。
伸缩型数组成员的规则:
1.) 伸缩型数组成员必须是最后一个数组成员
2.) 结构中必须至少有一个其他成员
3.) 伸缩型数组就像普通数组一样被声明,除了它的方括号内是空的
1 struct Student 2 9 { 3 10 int id; 4 11 char name[SIZE]; 5 12 int loveNums[]; 6 13 }; 7 14 8 15 struct Student * ptr = malloc (sizeof (struct Student) + 10 * sizeof (int));
联合
1 union Student 2 { 3 int id; 4 char name[SIZE]; 5 double height; 6 char en_name[SIZE]; 7 }; 8 union Student stu = {20092192}; 9 //union Student stu = {.name = "fangwenyu"}; 10 //union Student stu2 = stu;
因为联合只存储一个值,所以初始化的规则与结构的初始化不同。具体的,有3种选择:可以把一个联合初始化为同样类型的另一个联合;可以初始化联合的第一个元素; 或者,按照C99标准,可以使用一个指定初始化项目。
点运算符表示正在使用哪种数据类型。在同一个时间只能存储一个值。即使有足够的空间,也不能同时保存一个char类型和一个int类型的值。由您负责记住当前保存在联合中的数据的类型。
如同与指向结构的指针一起使用->运算符一样,可以与指向联合的指针一起来使用->运算符:
数组复合文字、结构体复合文字、联合体复合文字不同于字符串常量, 使用指针指向它们, 字符串常量内容不可以修改, 而其他复合文字内容可以修改
C的某些枚举属性不能延至C++中。例如,C允许对枚举变量使用运算符++,而C++不允许。因此,如果您的代码有可能会被加入C++程序中,那么在上面的例子中,您必须把color声明为int类型。这样该代码就既能工作在C下,也能工作在C++下
在使用整数常量的任何地方都能使用枚举常量。例如,在数组声明中可以把它们作为数组大小;在switch语句中,可用它们来作为标签。
名字空间(namespace)
在一个特定作用域内的结构标记、联合标记以及枚举标记都共享同一个名字空间,并且这个名字空间与普通变量使用的名字空间是不同的。这意味着,可以在同一个作用域内对一个变量和一个标记使用同一个名字,而不会产生错误;但是不能在同一作用域内使用名字相同的两个标记或名字相同的两个变量。例如,在C中下面的语句不会产生冲突:
struct rect {double x; double y;};
int rect;
然而,用两种不同的方式使用同一标识符会造成混乱;而且,C++不允许在同一作用域内对一个变量和一个标记使用同一个名字,因为它把标记和变量名放在同一个名字空间中。