坑
常见坑与最佳实践
Pitfalls & Best Practices
下面这些坑,几乎每个 C 程序员都踩过一遍。提前知道,能少熬几个夜。
坑 1:gets 已死,有事烧纸
gets() 不检查输入长度,你输入多长它就写多长,是缓冲区溢出漏洞的头号元凶,早已被 C11 标准废除。读一行永远用 fgets(buf, sizeof(buf), stdin),把长度传进去。
坑 2:字符串忘了 \0
手动往 char 数组里填字符却没补 '\0',printf("%s") 会一路打印到内存里的随机数据。记住:自己造的字符串,结尾一定补 '\0'。
坑 3:数组越界
C 不检查下标。int a[5] 你写 a[10],编译器不报错,运行时踩坏旁边内存,表现为"莫名其妙地出错,而且改一行就好了"。循环边界永远写 i < N,别写成 <=。
坑 4:未初始化 / 野指针
局部变量不会自动清零。int *p; *p = 5; 里 p 是个随机地址,写进去直接段错误。指针要么指向有效内存,要么置 NULL。
坑 5:整数溢出与优先级
int 最大约 21 亿,20 亿 + 2 亿 会溢出成负数。另外 &、| 的优先级比 == 还低,a & b == c 其实是 a & (b == c)——拿不准就加括号。
坑 6:switch 忘 break
漏写 break,程序会"贯穿"到下一个 case 继续执行。编译器开 -Wall 能提醒你,别浪费这个免费提醒。
记
C 生存守则
① 编译永远带 -Wall -Wextra,把警告当错误看。
② 指针声明即置 NULL,free 后再置 NULL。
③ 任何 malloc 后面跟着判 NULL,任何 fopen 后面跟着判 NULL。
④ 拿不准运算符优先级就加括号;拿不准字符串结尾就补 '\0'。