6. 运算符基础(下):关系、逻辑、条件与逗号

好,咱们接着聊运算符。上一节我们把算术运算符和赋值运算符讲透了,这一节要聊的这几个,说实话,在嵌入式开发里用的频率极高。关系运算符做判断,逻辑运算符组合条件,条件运算符写简洁分支,逗号运算符嘛……嗯,它有点特别,但用好了能写出很漂亮的代码。

6.1 关系运算符:>、<、>=、<=、==、!=

关系运算符,说白了就是比大小、判相等。它的结果只有两个:真(1)或假(0)。

运算符含义示例结果
>大于5 > 31
<小于5 < 30
>=大于等于5 >= 51
<=小于等于5 <= 40
==等于5 == 51
!=不等于5 != 50
⚠ 新手最容易犯的错:== 写成 =。我在项目中遇到过一位同事,调试了一下午,最后发现是 if(a = 5) 这种写法——赋值表达式的结果是 5,永远为真,条件永远成立。你想想看,这种 bug 多隐蔽。

我个人习惯,写相等判断时,会把常量写在左边:if(5 == a)。这样万一写成 if(5 = a),编译器直接报错,不会让你带着 bug 跑。

6.2 逻辑运算符:&&、||、!

逻辑运算符用来组合多个条件。C 语言里只有三个:

  • &&(逻辑与):两边都为真,结果才为真
  • ||(逻辑或):只要一边为真,结果就为真
  • !(逻辑非):取反,真变假,假变真

短路求值——这个必须记住

&& 和 || 有个重要特性:从左往右算,一旦结果确定了,右边就不算了。

  • 对于 &&:左边为假,右边直接跳过
  • 对于 ||:左边为真,右边直接跳过

我曾经在写一个温度传感器驱动时,遇到过这样的代码:

if (ptr != NULL && ptr->value > 100) {
    // 处理数据
}

这里短路求值就很重要。如果 ptr 是 NULL,右边 ptr->value 根本不会执行,也就不会发生空指针访问。你想想看,要是没有短路机制,这代码得崩多少次。

💡 我的建议:写 && 条件时,把「大概率假」的条件放左边,这样能更快跳过。写 || 时,把「大概率真」的条件放左边。虽然对性能影响微乎其微,但这是个好习惯。

6.3 条件运算符:?:

条件运算符是 C 语言里唯一的三目运算符。格式:

表达式1 ? 表达式2 : 表达式3

如果表达式1为真,整个表达式的结果就是表达式2的值;否则是表达式3的值。

举个例子,取两个数中的较大值:

int max = (a > b) ? a : b;

这比写 if-else 简洁多了。我在项目中经常用它来写一些简单的条件赋值,比如:

// 根据温度决定风扇转速
int speed = (temp > 50) ? 100 : 50;
⚠ 注意:条件运算符不要嵌套太深。我曾经见过有人写 a ? b ? c : d : e ? f : g,这种代码可读性极差。我的原则是:嵌套超过一层,老老实实写 if-else。

6.4 逗号运算符:,

逗号运算符可能是最容易被忽略的。它的作用很简单:从左到右依次执行每个表达式,整个表达式的结果是最后一个表达式的值。

int x = (a = 1, b = 2, a + b);  // x 的值是 3

嗯,这里要注意:逗号运算符的优先级是所有运算符里最低的。所以上面那个例子,括号不能省。

我在写 for 循环时经常用它:

for (int i = 0, j = 10; i < j; i++, j--) {
    // 同时从两端向中间遍历
}

还有在宏定义里,逗号运算符也很有用:

#define SWAP(a, b)  do { int tmp = a; a = b; b = tmp; } while(0)

这里用 do-while(0) 包裹,本质上也是利用了逗号运算符的思路——把多条语句组合成一个表达式。

💡 实用技巧:逗号运算符可以让你在只允许写一个表达式的地方,塞进多个操作。但别滥用,否则代码会变得很难读。

知识体系总览

下面这张图把这一节的核心内容串起来了,你可以对照着复习:

运算符基础(下)知识体系 关系运算符 > < >= <= == != 结果:真(1) 或 假(0) ⚠ 别把 == 写成 = 建议:常量放左边,如 5 == a 逻辑运算符 && || ! 短路求值:结果确定就停 ⚠ 注意执行顺序 建议:大概率假的条件放左边 条件运算符 表达式1 ? 表达式2 : 表达式3 唯一的三目运算符 ⚠ 不要嵌套过深 建议:超过一层就用 if-else 逗号运算符 expr1, expr2, ..., exprN 结果 = 最后一个表达式的值 ⚠ 优先级最低,记得加括号 建议:for 循环和宏定义中常用

这一节的内容就这些。关系运算符做判断,逻辑运算符组合条件,条件运算符写简洁分支,逗号运算符做顺序求值。每个都有它的用武之地,也都有需要注意的坑。写代码时多留个心眼,尤其是短路求值和 == 与 = 的区别,这两个是面试和笔试的高频考点,也是实际项目中容易出 bug 的地方。