/* ... */ 不可嵌套。/ 和 * 間無空格即視為註釋開始:y = x/*p; → y = x 後被註釋。\ 行接續符:剔除換行符,前後無空格。亦作轉義字符開頭。// 交換兩變量無需暫存 a ^= b; b ^= a; a ^= b; // 優先級陷阱 0x01 << 2 + 3; // + 優先於 <<,等價 0x01 << 5 = 32 // 32 位系統移位限制 // 移位位數不能 ≥ 數據位寬(32),不能 < 0(否則未定義行為) // 有符號數右移:符號位跟隨移動 // 正數高位補 0;負數高位補 0/1 視編譯器(Turbo C 等補 1) // 常用位操作宏 #define SETBIT(x,y) ((x) |= (y)) #define CLRBIT(x,y) ((x) &= ~(y)) #define TOGLBIT(x,y) ((x) ^= (y)) #define TESTBIT(x,y) ((x) & (y)) // 按位號操作 #define SETBIT(x,y) ((x) |= 1 << (y)) #define CLRBIT(x,y) ((x) &= ~(1 << (y)))
打包初始化列表:char a[10] = {"abcde"};
// 未定義行為:同一序列點多次修改同一變量 i = 3; (++i)+(++i)+(++i); // TCC:15, VC6:16, GCC:18 → 不要這樣寫 // 後綴 ++/--:在遇到 , 或 ; 結束當前計算單元後才自增減 i = 3; (i++)+(i++)+(i++); // 依編譯器不同 // 逗號表達式:左求值、右求值,整體值為最右表達式值 j = (i++, i++, i++); // j=2, i=3 j = (++i, ++i, ++i); // j=3, i=3
C99 規定商向零截斷,餘數符號與被除數同號:
3 / 2 = 1 3 % 2 = 1 -3 / 2 = -1 -3 % 2 = -1 3 / -2 = -1 3 % -2 = 1 -3 / -2 = 1 -3 % -2 = -1
. [] () 高於 *(解引用)== != 高於位運算== != 高於賦值非 C 語言核心,屬編譯器功能。
__LINE__、__FILE__、__DATE__、__TIME__、__STDC__#define EMPTY 和 # define EMPTY 皆合法。#error 強制編譯報錯:#error message。#line 修改行號/文件名:#line 100 "test.c"。#pragma 編譯器指令。# 字串化,## 符號連接。#if !defined(NDEBUG)
#define assert(p) if(!(p)){fprintf(stderr,\
"Assertion failed: %s, file %s, line %d\n", #p, __FILE__, __LINE__); abort();}
#else
#define assert(p)
#endif
int main(void) // 無參 int main(int argc, char *argv[]) // 有參 int main(int argc, char **argv) // 等價
argc:參數總數(含程序名)。argv[0]:程序名。argv[i]:第 i 參數。例:./a.out Love Live ! → argc=4,argv[1]="Love" 等。
int a[5]; 編譯器分配連續記憶體,a 為首地址別名,不可修改。&a[0] 首元素地址;&a 整個陣列地址(值相同,類型義不同)。a 作右值 = &a[0](首元素地址);a 不能作左值。int main() {
char a[5] = {'A','B','C','D'};
char (*p3)[5] = &a; // 類型完全匹配
char (*p4)[5] = a; // 右值為 char*,隱式轉換(值相同)
// p3+1 指向下一個 5-char 陣列,偏移 5 bytes
// p4+1 同理(因類型相同)
}
free/delete 後未置 NULL(僅釋放記憶體,指標本身仍存)。char *p = NULL; // 定義即初始化 // 使用... free(p); p = NULL; // 用後即置空
一維陣列作參數,編譯器自動轉為首元素指標:void f(int a[]) ≡ void f(int *a)。