1. 运算符优先级:那些年我们踩过的坑
刚学C语言那会儿,我最头疼的就是运算符优先级问题。明明代码逻辑没问题,运行结果却总是莫名其妙。后来才发现,问题出在运算符的"隐形规则"上。比如下面这段代码:
int result = 5 + 3 * 2;你觉得result的值是多少?如果是11,说明你已经掌握了优先级;如果是16,那可得好好看这部分了。C语言的运算符优先级就像数学里的"先乘除后加减",但更复杂。我总结了个顺口溜:
单目 > 算术 > 移位 > 关系 > 等号 > 位与 > 位异或 > 位或 > 逻辑与 > 逻辑或 > 赋值
具体来说:
- 单目运算符(!、++、--等)优先级最高
- 接着是算术运算符(*、/、%高于+、-)
- 关系运算符(>、<、>=、<=)又高于等号运算符(==、!=)
- 最后才是各种赋值操作
实际编程时,我强烈建议多用括号。比如:
// 模糊写法 if (a & b == c) // 清晰写法 if ((a & b) == c)2. 排序算法实战:从冒泡到选择
2.1 冒泡排序:菜鸟的入门必修课
记得第一次写冒泡排序,我写出了这样的"神逻辑":
for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (a[j] > a[j+1]) { swap(a[j], a[j+1]); } } }结果当然是数组越界崩溃。正确写法应该是:
for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-1-i; j++) { if (a[j] > a[j+1]) { int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; } } }这里有两个关键点:
- 外层循环只需n-1次,因为n-1轮后最后一个元素自然有序
- 内层循环范围随轮数减少,因为每轮都会把当前最大值"冒泡"到最后
2.2 选择排序:效率的小提升
选择排序比冒泡稍高效,因为它减少了交换次数。但新手常犯的错误是:
for (int i = 0; i < n; i++) { int min = a[i]; // 错误!应该记录下标而非值 for (int j = i+1; j < n; j++) { if (a[j] < min) { min = a[j]; } } // 缺少交换操作 }正确的姿势应该是:
for (int i = 0; i < n-1; i++) { int min_idx = i; for (int j = i+1; j < n; j++) { if (a[j] < a[min_idx]) { min_idx = j; } } if (min_idx != i) { int temp = a[i]; a[i] = a[min_idx]; a[min_idx] = temp; } }3. 经典题目精讲:水仙花数与斐波那契
3.1 水仙花数的坑
水仙花数(三位数各位立方和等于自身)看似简单,但新手常犯两个错误:
- 错误处理数字位数:
int a = i / 100; // 百位 int b = i / 10 % 10; // 十位 int c = i % 10; // 个位- 混淆==和=:
if (i = a*a*a + b*b*b + c*c*c) // 错误!应该是==3.2 斐波那契的递归陷阱
斐波那契数列的递归实现虽然优雅,但直接套公式会掉坑:
long long fib(int n) { if (n <= 0) return -1; if (n == 1) return 0; // 注意!题目要求第一项是0 if (n == 2) return 1; return fib(n-1) + fib(n-2); }这里特别要注意:
- 题目要求的数列起始项可能和常规定义不同
- 递归解法时间复杂度是O(2^n),对于大数会非常慢
4. 调试技巧:我的救命稻草
初学阶段,我总结了几条调试铁律:
- 打印大法好:在关键位置插入printf
printf("调试信息:i=%d, a[i]=%d\n", i, a[i]);- 边界检查:数组操作前先检查下标
if (index >= 0 && index < array_size) { // 安全操作 }逐步缩小法:注释掉部分代码,逐步定位问题
橡皮鸭调试:向没有编程背景的人解释你的代码逻辑
记得有次调试三小时,最后发现是把==写成=了。从此我养成了写比较表达式时把常量放前面的习惯:
if (5 == x) // 这样写如果漏写=号会报错5. 代码优化:从能跑到高效
当你的代码能正确运行后,可以考虑这些优化:
- 减少循环次数:
// 优化前 for (int i = 0; i < strlen(s); i++) // 优化后 int len = strlen(s); for (int i = 0; i < len; i++)- 用位运算代替乘除:
x = x * 2; → x = x << 1; x = x / 2; → x = x >> 1;- 避免重复计算:
// 优化前 area = 3.14159 * r * r; // 优化后 const double PI = 3.14159; area = PI * r * r;这些技巧在我完成课设时帮了大忙,特别是处理大数据量时,效率提升非常明显。