承接上文,位域本質是特殊結構體,支援指針訪問與復合位運算賦值。
#include <stdio.h>
struct BS {
unsigned a : 1;
unsigned b : 3;
unsigned c : 4;
};
int main() {
struct BS bit = {0}, *pbit = &bit;
// 直接賦值
bit.a = 1;
bit.b = 7;
bit.c = 15;
printf("初始: %d,%d,%d\n", bit.a, bit.b, bit.c); // 1,7,15
// 指針操作 + 復合位運算
pbit->a = 0;
pbit->b &= 3; // 相當於 pbit->b = pbit->b & 3 -> 7 & 3 = 3
pbit->c |= 1; // 相當於 pbit->c = pbit->c | 1 -> 15 | 1 = 15
printf("修改後: %d,%d,%d\n", pbit->a, pbit->b, pbit->c); // 0,3,15
return 0;
}
typedef 原類型名 新類型名;
typedef 在編譯階段處理,而 #define 在預處理階段單純文本替換。_t 後綴(如 uint32_t)。typedef int INTEGER;
INTEGER a, b; // 等同 int a, b;
typedef char NAME[20];
NAME a1, a2, s1, s2; // 等同 char a1[20], a2[20], s1[20], s2[20];
typedef char *PSTR;
PSTR p1, p2; // 等同 char *p1, *p2;
// 注意:typedef char *PSTR; 後 PSTR 是指針類型
// 若寫 typedef char * PSTR; const PSTR p; p 是 char * const (常量指針),非 const char*
typedef struct Stu {
char name[20];
int age;
char sex;
} STU;
STU body1, body2; // 等同 struct Stu body1, body2;
// 甚至可匿名結構體直接別名
typedef struct { int x, y; } Point;
Point p1 = {1,2};
// 原聲明:int (*cmp)(const void*, const void*);
typedef int (*CmpFunc)(const void*, const void*);
void sort(void *base, size_t n, size_t sz, CmpFunc cmp); // 極度清晰
| 特性 | typedef | #define |
|---|---|---|
| 處理階段 | 編譯期 | 預處理期 |
| 語義 | 類型別名 | 文本替換 |
| 指針聲明 | typedef char *PSTR; const PSTR p; → char * const p | #define PSTR char *; const PSTR p; → const char *p (語義不同!) |
| 作用域 | 遵循 C 作用域規則 | 無作用域,全局替換 |
| 調試符號 | 保留類型信息 | 無類型信息 |
& | ^ ~ << >> 兩類(邏輯/移位),可構成復合賦值 &= |= ^= <<= >>=。types.h 統一定義 u8/u16/u32/i8/i16/i32/bool_t 等別名,禁用原始類型。-Wswitch-enum,讓編譯器守護完整性。