# 的妙用#include
#define _mir(a) #a
int main() {
char *s = _mir(
struct _st {
int a;
int b;
int c;
};
);
printf("%s\n", s);
return 0;
}
輸出:
struct _st { int a; int b; int c; };
解析:# 將右側參數轉為字串;## 連接左右參數。宏參數以逗號分隔,換行與空白會被處理成同一行。適合包含特殊字元的字串,避免大量跳脫字元,但參數中不能有逗號。
struct _st { int a; int b; int c; };
printf("%d\n", &((struct _st*)0)->b); // 輸出 4
原理:以位址 0 作為結構體基址,成員 b 的位址即為其偏移量。編譯器優化避免了實際解參考導致的異常。這是 offsetof 宏的核心實現原理。
struct _st {
int a : 1;
int b : 1;
int c : 1;
} s = { .c = 1, .b = 0, .a = 0 };
printf("%d %d %d %d\n", sizeof(s), s.a, s.b, s.c);
// 輸出:4 0 0 -1
重點:
.c = 1 可打亂順序,提升大型結構體可讀性int a : 1 限制欄位寬度為 1 位元,展現 C 對位元操作的親和力s.c 輸出 -1:1 位元有號整數全 1 時代表 -1(補數表示),有號/無號混用極危險char a[10] = "hello";
0[a] = 'x'; // 等價於 a[0] = 'x'
printf("%s\n", a); // 輸出 xello
for (int i = 0; i < 10; i++)
printf("%c", (rand() % 10)["0123456789"]); // 輸出 10 位隨機數字
原理:a[i] 等價於 *(a + i),加法交換律使 i[a] 等價於 *(i + a)。字串常值本質是 char*,同樣支援下標運算。
void func(char a[10]) {
printf("%p %p\n", &a, &a[0]); // 兩值不同!
}
int main() {
char a[10];
printf("%p %p\n", &a, &a[0]); // 兩值相同
func(a);
}
解析:
&a(陣列位址)與 &a[0](首元素位址)數值相同char *a,&a 變為指標變數自身在堆疊上的位址,&a[0] 仍為呼叫者傳入陣列首元素位址