C

C 知识量:16 - 74 - 317

10.8 其他重要内容><

变长数组- 10.8.1 -

C语言在C99标准中新增了变长数组(VLA),也就是允许使用变量表示数组的维度,例如:

int m = 2;
int n = 3;
int box[m][n]; //声明变长数组

变长数组有一些限制,比如:变长数组必须是自动存储类别,也就是说无论在函数中声明还是作为函数形参声明,都不能使用static或extern存储类别说明符,而且不能在声明中初始化它们。

需要注意:

  • 变长数组的“变”指的是在创建数组时,可以使用变量来指定数组的维度,而不是指可以修改已创建的数组的大小。

  • 在C11标准中,变长数组是一个可选特性,不是必须强制实现的特性,因此,不是所有编译器都支持变长数组。

在声明一个将变长数组作为形参的函数时,需要首先声明变长数组的两个维度,然后是变长数组本身,顺序不能错。例如:

int sum_vla(int rows, int cols, int box[rows][cols]);//正确的声明
int sum_vla(int box[rows][cols], int rows, int cols);//错误的声明

可以省略原型中的形参名,但是必须用星号(*)来代替省略的维度:

int sum_vla(int, int, int box[*][*]);

下面利用变长数组,实现一个能够计算任意大小的二维int数组元素之和的函数:

#include <stdio.h>
//声明计算任意大小的二维int数组元素之和的函数
int sum_vla(int rows, int cols, int box[rows][cols]);

int main(void) {
    int rows = 3;
    int cols = 4;
    int box[rows][cols]; //声明二维变长数组
    //赋值变长数组
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            box[i][j] = i + j;
    //打印变长数组
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            printf("row:%d col:%d value:%d\n", i, j, box[i][j]);
    //调用函数计算数组元素的和
    printf("Sum of all elements = %d\n", sum_vla(rows, cols, box));
    system("pause");
    return 0;
}
//定义计算任意大小的二维int数组元素之和的函数
int sum_vla(int rows, int cols, int box[rows][cols]) {
    int r;
    int c;
    int tot = 0;
    for (r = 0; r < rows; r++)
        for (c = 0; c < cols; c++)
            tot += box[r][c];
    return tot;
}

运行结果为:

row:0 col:0 value:0
row:0 col:1 value:1
row:0 col:2 value:2
row:0 col:3 value:3
row:1 col:0 value:1
row:1 col:1 value:2
row:1 col:2 value:3
row:1 col:3 value:4
row:2 col:0 value:2
row:2 col:1 value:3
row:2 col:2 value:4
row:2 col:3 value:5
Sum of all elements = 30

变长数组允许动态内存分配,可以在程序运行时指定数组的大小。而普通的数组都是静态内存分配,在编译时就确定数组的大小。

复合字面量- 10.8.2 -

C语言的C99标准增加了复合字面量。字面量是除符号常量以外的常量。例如:100是int类型的字面量,3.14是double类型的字面量,'A'是char类型的字面量,"world"是字符串字面量等等。对于数组,复合字面量类似数组初始化列表,前面是用括号括起来的类型名,以下是一个示例:

int box[2] = {100, 200}; //普通的数组
(int [2]){100, 200};     //复合字面量

去掉数组名,留下的int[2]就是复合字面量的类型名。跟数组一样,在初始化时复合字面量也可以省略大小,编译器会自动计算数组当前的元素个数:

(int []){100, 200};

由于复合字面量是匿名的,所以不能先创建再使用,必须在创建的同时使用它,例如:

int * p;
p = (int [2]){100, 200};

以上代码中,复合字面量的类型名代表着首元素的地址,因此,可以赋值给指针p。

除此之外,还可以将复合字面量作为实参直接传递给函数,例如:

int sum(int b[]);
int tot;
tot = sum((int [2]){100, 200});

在函数参数中使用复合字面量的好处就是,在信息传入函数前不必先创建数组。复合字面量是提供只临时需要的值的一种手段,它具有块作用域,也就是说一旦离开定义复合字面量的块,程序将无法保证该字面量是否存在。注意:复合字面量的定义在最内层花括号中。