一、变长数组
C90中的数组的大小必须是编译期间可求出的常数值,而C99做了很大改进,允许数组的[ ]中的值是整形变量或是整形表达式。这就解释了下面的情况:
int n;
scanf ("%d", &n);
int array[n];
虽然n确实是需要运行时动态确定的变量,但是在C99中,以这种变量作为数组大小的形式已经是允许的了。这样的数组就被称之为“变长数组”。注意:变长数组是指用整形变量或表达式声明或定义的数组,而不是说数组的长度会随时变化,变长数组在其生存期内的长度同样是固定的。如下面的例子:
........
fun (10);
.........
void fun(int n)
{
int vla[n];
n += 10;
printf ("vla takes %d bytes/n", sizeof vla);
}
执行的结果是40,虽然n的值在声明了数组vla之后发生了变化,但是vla不会因此而改变大小,因为变长数组一旦被声明,其大小就会保持不变直到生命期结束。
另外,变长数组不允许是静态数组或是具有外部链接性质的数组。因为外部数组存放在数据段,它们占用的空间必须在编译时确定。变长数组也不能是struct或是union的成员,因为它们的大小也必须在编译期确定。
二、可伸缩数据成员
这个特征是针对struct结构来说的。正如上文说到,结构体的成员中不能够包含变长数组,那么如果结构体的某个数组需要在运行时动态确定大小怎么办呢?C99提供了一种方法,如下例
struct polygon
{
int edgeCount;
double coordinate[];
};
它告诉编译器,polygon有一个可伸缩数据成员coordinate,它不占用任何空间(因为sizeof polygon == sizeof edgeCount),只有在动态存储分配后,coordinate才有意义。
struct polygon *p;
int temp;
....... // 为temp赋值
p = malloc (sizeof (struct polygon) + 16 * temp);
对于可伸缩数据成员的struct,至少要有另外一个可在编译时确定大小的对象,并且可伸缩数组成员必须是struct结构中的最后一个成员。
三、Designated Initializer
C99对于复合类型(struct、union、array)的初始化有了新的,更加灵活的方法。体现在,对于数组来说,可以对任意指定的元素进行初始化,而不是像从前那样,如果想初始化第n个元素,那么一定要将之前的元素都初始化。现在我们可以这样来做:
int array[10] = {[4] = 2};
int array[10] = {[0] = 0, [2] = 2, [5] = 5, [9] = 9};
int array[100] = {[0] = 0, 1, 2, 3, 4, [95] = 95, 96, 97, 98, 99};
这就是Designated Initializer的威力!我们可以随便选择某个/某些元素初始化。
对于struct或是union来说,同样也有灵活的方法。如有一个结构体
struct demo
{
int n;
double d;
char array[5];
};
先要求初始化demo变量,把d赋值为3.5,array[4]赋值为‘M’。C90要这样写 :
struct demo s = {0, 3.5, {'/0', '/0', '/0', '/0', 'M'}}; 而C99允许这样写:
sturct demo s = {.d = 3.5, .array[4] = 'M'}; 或是 sturct demo s = {.d = 3.5, .array[4] = {[4] = 'M'}};
如果定义一个demo数组,含有10个元素,首尾元素分别初始化为{4, 7.8, "ABC"}和{8, 3.2, "XYZ"}, 则可这样写:
struct demo demoArray[10] = {
[0] = {.n = 4, .d = 7.8, .array = "ABC"},
[9] = {.N = 8, .d = 3.2, .array = "XYZ"}
};或是简单点,直接就是
struct demo demoArray[10] = {
[0] = {4, 7.8, "ABC"},
[9] = {8, 3.2, "XYZ"}
};