if (x = 5)总进分支是因为=是赋值运算符,表达式结果为5,C中非零即真;while (c = ' ' || c == '\t')死循环因=优先级低于||,导致c恒被赋值为1;字符串和数组不可用==或=直接比较或赋值。

为什么if (x = 5)总进分支?——赋值表达式在条件中自动转为真值
因为=是赋值运算符,if (x = 5)不是判断,而是把5塞进x,然后拿这个结果(即5)当条件用。C里非零即真,所以整个if永远成立。这不是bug,是语言定义——但它是**逻辑错误的高发区**。
- 所有条件语句(
if、while、for的判断部分)中,除非你明确想“先赋值再判断”,否则写=就是错 - 编译器如
gcc -Wall会警告assignment in conditional context,但别依赖它——有些场景它不报(比如while ((c = getchar()) != EOF)是合法且常见的) - 若真要赋值后判断,显式写出意图:
if ((x = y) != 0)或if ((x = y))(注意括号),避免歧义
while (c = ' ' || c == '\t')为何死循环?——优先级陷阱+赋值副作用
这里=的优先级比||低,整条表达式被解析为:c = (' ' || c == '\t' || c == '\n')。而' '的ASCII是32,非零,整个逻辑或结果恒为1,于是c被反复赋值为1,条件永远为真。
- 这不是“写错了”,是编译器严格按优先级规则执行的结果
- 正确写法必须全部用
==:while (c == ' ' || c == '\t' || c == '\n') - 更安全的写法是拆开:先读字符,再单独判断,例如
while (isspace(c)) c = getchar();(需#include)
字符串不能用==比较,数组也不能用=赋值
这两类错误和=/==混淆无关,但常被初学者一并踩中,属于“符号直觉误导”:
-
char s1[10] = "abc"; char s2[10]; s2 = s1;→ 错误!数组名不是左值,=不支持整体赋值;要用strcpy(s2, s1)或strncpy(s2, s1, sizeof(s2)-1) -
if (s1 == s2)→ 错误!比较的是两个地址(指针值),不是内容;要用strcmp(s1, s2) == 0 - 字符变量可用
==(如if (c == 'a')),但字符串字面量"a"是地址,char c = 'a';才是字符——单引号 vs 双引号,差一个类型
如何一眼识别该用=还是==?——三秒自查口诀
写完条件语句后,默念这三句:
立即学习“C语言免费学习笔记(深入)”;
- “我要改它的值吗?” → 是,用
=;否,用== - “左边是个能被改的变量吗?” → 如果是
5 == x,左边是常量,只能比较,不可能赋值,必须用== - “我是不是在初始化变量?” → 声明时
int a = 5;中的=是初始化,不是赋值运算符,不受上述规则限制(但它仍是=,不是==)
最危险的从来不是不会写,而是写完没多看一眼——尤其在快速调试时删掉一个=就变成==,加多一个又变回=。这种错误不报错、不崩溃,只悄悄让逻辑跑偏。











