当前位置:嗨网首页>书籍在线阅读

24-复合字面量

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

10.9 复合字面量

假设给带 int 类型形参的函数传递一个值,要传递 int 类型的变量,但是也可以传递 int 类型常量,如 5 。在C99标准以前,对于带数组形参的函数,情况不同,可以传递数组,但是没有等价的数组常量。C99新增了复合字面量(compound literal)。字面量是除符号常量外的常量。例如, 5int 类型字面量, 81.3double 类型的字面量, 'Y'char 类型的字面量, "elephant" 是字符串字面量。发布C99标准的委员会认为,如果有代表数组和结构内容的复合字面量,在编程时会更方便。

对于数组,复合字面量类似数组初始化列表,前面是用括号括起来的类型名。例如,下面是一个普通的数组声明:

int diva[2] = {10, 20};

下面的复合字面量创建了一个和 diva 数组相同的匿名数组,也有两个 int 类型的值:

(int [2]){10, 20}        // 复合字面量

注意,去掉声明中的数组名,留下的 int [2] 即是复合字面量的类型名。

初始化有数组名的数组时可以省略数组大小,复合字面量也可以省略大小,编译器会自动计算数组当前的元素个数:

(int []){50, 20, 90} // 内含3个元素的复合字面量

因为复合字面量是匿名的,所以不能先创建然后再使用它,必须在创建的同时使用它。使用指针记录地址就是一种用法。也就是说,可以这样用:

int * pt1;
pt1 = (int [2]) {10, 20};

注意,该复合字面量的字面常量与上面创建的 diva 数组的字面常量完全相同。与有数组名的数组类似,复合字面量的类型名也代表首元素的地址,所以可以把它赋给指向 int 的指针。然后便可使用这个指针。例如,本例中* pt110pt1[1]20

还可以把复合字面量作为实际参数传递给带有匹配形式参数的函数:

int sum(const int ar[], int n);
...
int total3;
total3 = sum((int []){4,4,4,5,5,5}, 6);

这里,第 1 个实参是内含 6int 类型值的数组,和数组名类似,这同时也是该数组首元素的地址。这种用法的好处是,把信息传入函数前不必先创建数组,这是复合字面量的典型用法。

可以把这种用法应用于二维数组或多维数组。例如,下面的代码演示了如何创建二维 int 数组并存储其地址:

int (*pt2)[4];    // 声明一个指向二维数组的指针,该数组内含2个数组元素,
                  // 每个元素是内含4个int类型值的数组
pt2 = (int [2][4]) { {1,2,3,-9}, {4,5,6,-8} };

如上所示,该复合字面量的类型是 int [2][4] ,即一个 2 × 4int 数组。

程序清单10.19把上述例子放进一个完整的程序中。

程序清单10.19  flc.c 程序

// flc.c -- 有趣的常量
#include <stdio.h>
#define COLS 4
int sum2d(const int ar[][COLS], int rows);
int sum(const int ar[], int n);
int main(void)
{
     int total1, total2, total3;
     int * pt1;
     int(*pt2)[COLS];
     pt1 = (int[2]) { 10, 20 };
     pt2 = (int[2][COLS]) { {1, 2, 3, -9}, { 4, 5, 6, -8 } };
     total1 = sum(pt1, 2);
     total2 = sum2d(pt2, 2);
     total3 = sum((int []){ 4, 4, 4, 5, 5, 5 }, 6);
     printf("total1 = %d\n", total1);
     printf("total2 = %d\n", total2);
     printf("total3 = %d\n", total3);
     return 0;
}
int sum(const int ar [], int n)
{
     int i;
     int total = 0;
     for (i = 0; i < n; i++)
          total += ar[i];
     return total;
}
int sum2d(const int ar [][COLS], int rows)
{
     int r;
     int c;
     int tot = 0;
     for (r = 0; r < rows; r++)
          for (c = 0; c < COLS; c++)
               tot += ar[r][c];
     return tot;
}

要支持C99的编译器才能正常运行该程序示例(目前并不是所有的编译器都支持),其输出如下:

total1 = 30
total2 = 4
total3 = 27

记住,复合字面量是提供只临时需要的值的一种手段。复合字面量具有块作用域(第12章将介绍相关内容),这意味着一旦离开定义复合字面量的块,程序将无法保证该字面量是否存在。也就是说,复合字面量的定义在最内层的花括号中。