首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

神奇的 C 語言:預處理器、結構體位元欄位、陣列指標等進階技巧大揭秘

     編輯:關於C

技巧一:字串化運算子 # 的妙用

#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] 仍為呼叫者傳入陣列首元素位址
  • 這是 C 語言「陣列參數退化為指標」規則導致的經典陷阱
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved