这是一个非常经典且容易出错的写法,因为它涉及到赋值运算符和关系运算符的混淆。

(图片来源网络,侵删)
while(x=0) 这个循环永远不会执行,因为循环条件在第一次判断时就被计算为 0(即 false)。
分步解析
让我们把这个表达式拆开来看:
x = 0 是什么?
在C语言中, 是赋值运算符(Assignment Operator),它的作用是将右侧的值赋给左侧的变量。
x = 0 这条语句做了两件事:

(图片来源网络,侵删)
- 赋值:将数值
0存储到变量x中。 - 返回值:赋值表达式的值,就是被赋的值本身。
x = 0这个表达式的值就是0。
while(...) 如何工作?
while 循环的语法是 while (expression),它会不断检查 expression 的值:
- 如果表达式的值为非零(在C语言中,非零即代表
true),则执行循环体内的代码。 - 如果表达式的值为零(在C语言中,零即代表
false),则终止循环。
结合起来分析 while(x=0)
- 程序首先进入
while循环的条件判断部分。 - 它执行赋值表达式
x = 0。- 变量
x的值被设置为0。 - 整个表达式
x = 0的计算结果为0。
- 变量
while循环检查这个结果,发现结果是0(false)。- 循环条件不满足,循环直接终止,循环体内的代码一次都不会被执行。
常见的错误与正确的写法
程序员在写 while 循环时,通常的意图是判断 x 是否等于 0,而不是给 x 赋值 0。
错误的写法 (意图是判断是否等于0)
int x = 5;
while(x = 0) { // 错误!这是一个死循环吗?不,是永不执行的循环。
printf("This will never be printed.\n");
}
printf("x is now %d\n", x); // 输出: x is now 0
正确的写法 (判断是否等于0)
在C语言中,用于比较两个值是否相等的是 (双等号),这是关系运算符。
int x = 5;
while(x == 0) { // 正确!判断 x 的值是否等于 0。
printf("This will also never be printed.\n");
}
printf("x is still %d\n", x); // 输出: x is still 5
在这个正确的例子里,x 的值没有被改变,循环条件 x == 0 为 false,所以同样不会进入循环。

(图片来源网络,侵删)
一个生动的例子:while(x=1)
为了更好地理解赋值表达式在 while 循环中的作用,我们来看另一个常见的错误:while(x=1)。
int x = 0;
printf("Initial x: %d\n", x); // 输出: Initial x: 0
while(x = 1) { // 错误!意图可能是 x != 1
printf("Inside the loop. x is %d\n", x);
x = 2; // 假设在循环里我们改变了 x 的值
break; // 加上 break 防止死循环
}
printf("After the loop. x is %d\n", x); // 输出: After the loop. x is 1
分析 while(x=1):
- 循环开始,执行
x = 1。x的值被设置为1。- 表达式
x = 1的值为1(非零,即true)。
while循环条件为true,进入循环。- 循环结束后,由于
x在每次循环开始时都会被重新赋值为1,所以这个循环会无限进行下去,成为一个死循环。
如何避免这种错误?
-
养成良好的编码习惯:在写
if或while的条件时,将常量放在左边,这是一个广为流传的技巧,可以有效防止这种错误。- 错误:
if (x = 5) - 正确:
if (5 == x) - 如果你误写成
if (5 = x),编译器会立刻报错,因为5是一个常量,不能被赋值,这样你就能马上发现问题并修正为if (5 == x)。
- 错误:
-
开启编译器的警告级别:现代C编译器(如GCC, Clang, MSVC)通常有警告选项(如
-Wall),能够检测到在条件判断中使用了赋值表达式并给出警告。永远不要忽略编译器的警告!
| 表达式 | 名称 | 作用 | while(x=0) 的结果 |
|---|---|---|---|
x = 0 |
赋值运算符 | 将 0 赋给 x,表达式的值为 0 |
永不执行 (条件为 false) |
x == 0 |
关系运算符 | 判断 x 是否等于 0,表达式的值为 0 或 1 |
永不执行 (条件为 false) |
while(x=1) |
赋值运算符 | 将 1 赋给 x,表达式的值为 1 |
死循环 (条件永远为 true) |
记住这个关键点: 是赋值, 是判断相等,在 while 循环的条件中,几乎总是需要使用 。
