C99 引入的復合字面量,允許在程式中直接建立「無名稱的數組或結構體常量」,語法像類型轉換加上初始化列表:
// 傳統:必須先宣告變數
int arr[3] = {1, 2, 3};
func(arr);
// C99:直接建立匿名數組傳遞
func((int [3]){1, 2, 3});
// 甚至可省略大小,由初始化列表推導
func((int []){1, 2, 3, 4, 5});
本質上,它產生一個無名稱物件,具有自動儲存期限(塊作用域內)或靜態儲存期限(檔案作用域),其值為指向該物件首元素的指標。
(型別名) { 初始化列表 }
// 例:
(int [2]){10, 20} // 匿名 int[2] 數組
(int []){10, 20, 30} // 匿名 int[3] 數組
(struct Point){1, 2} // 匿名結構體
型別名 就是宣告時去掉變數名的部分:int arr[2] → int [2]。
int sum(int *arr, int n) {
int s = 0;
for (int i = 0; i < n; i++) s += arr[i];
return s;
}
int total = sum((int []){1, 2, 3, 4, 5}, 5); // 無需預先定義變數
這完美契合「常量即值」的語義,避免汙染作用域。
int *p = (int []){10, 20, 30};
printf("%d\n", *p); // 10
printf("%d\n", p[1]); // 20
此處 p 指向匿名數組首元素,生命週期持續到包含塊結束。
// 二維數組
int (*p)[4] = (int [2][4]){{1,2,3,4}, {5,6,7,8}};
// 結構體
struct Point { int x, y; };
struct Point *pt = &(struct Point){3, 4}; // 取址得指標
printf("(%d, %d)\n", pt->x, pt->y);
#include <stdio.h>
#define COLS 4
void sum1d(int a[], int n);
void sum2d(int a[][COLS], int rows);
int main(void) {
// 1D 匿名數組
int *p1 = (int [2]){10, 20};
sum1d(p1, 2);
// 2D 匿名數組
int (*p2)[COLS] = (int [2][COLS]){{1,2,3,4}, {5,6,7,8}};
sum2d(p2, 2);
// 直接傳遞
sum1d((int []){1,2,3,4}, 4);
return 0;
}
void sum1d(int a[], int n) {
int tot = 0;
for (int i = 0; i < n; i++) tot += a[i];
printf("1D sum = %d\n", tot);
}
void sum2d(int a[][COLS], int rows) {
int tot = 0;
for (int i = 0; i < rows; i++)
for (int j = 0; j < COLS; j++)
tot += a[i][j];
printf("2D sum = %d\n", tot);
}
| 位置 | 儲存期限 | 生命週期 |
|---|---|---|
| 函數內部 (塊作用域) | 自動 | 進入塊建立,離開塊銷毀 |
| 函數外部 (檔案作用域) | 靜態 | 程式啟動建立,結束銷毀 |
關鍵點:塊作用域的復合字面量,其物件在塊結束時銷毀,不可將指標返回給外層(同區域變數指標)。
-std=c99 或更新)。