编译器如何解释`if(!(a=10))`?

问题描述

我有一个家庭作业,我认为教授打错了,输入了 if(!(a=10)) 而不是 if(!(a==10))。然而,当被问及这是否是错别字时,她告诉我“假设方程是正确的,然后给出你的答案。”具体来说,赋值是描述程序的行为:

#include <stdio.h>

int main() {
      int a = 100;
      while (1) {
          if (!(a=10)) {
              break;
          } 
      }
      return 0; 
}

如果攻击性代码读取 (!(a==10)) 则程序将进入 if 循环,到达 break退出两个循环,这对于 C 编程的初学者课程很有意义.

但是,如果代码真的要读取 (!(a=10)),那么我不知道编译器会解释它的含义。我确实知道代码可以编译,当你在 UNIX 中运行它时,它只允许你使用键盘输入任何你想要的东西,比如说数字“7”,然后你按下回车键,它移动到一个新行,并且您可以输入“dog”,然后移至新行,如此反复,它永远不会退出回命令行。那么(1)编译器如何解释(!(a=10))?以及(2)为什么该程序允许您永远继续输入条目?

谢谢!

解决方法

对于第一个问题, if( !(a=10) ){break;} 是什么意思, 相当于

a = 10; if(!a) {break;}

对于 10 的值,!a 将是 0 并且它永远不会中断 while 循环。 在这个特定的例子中,如果你分配 if(!(a=0)),那么它将退出循环;

对于第二个问题,您的示例中没有代码。 但是第一个问题的答案可以在这里扩展,因为循环永远不会中断,它会不断询问输入值。

,

来自 C 标准 (6.5.3.3 Unary arithmetic operators ¶5)

5 逻辑否定运算符 ! 的结果为 0 如果 它的操作数比较不等于 0,如果它的操作数的值是 1 比较等于 0。结果的类型为 int。表达式 !E 是 相当于 (0==E)

所以根据引用 if 语句

if (!(a=10)) {

相当于

if ( ( a = 10 ) == 0 ) {

作为赋值子表达式的值,a = 10 等于 10 即它不等于 0 那么 if 语句的条件计算为逻辑假并且if 语句的子语句将无法获得控制权,您将有一个无限的 while 循环。

其实你可以重写这个while循环

  while (1) {
      if (!(a=10)) {
          break;
      } 
  }

以下方式效果相同

  while ( ( a = 10 ) ) {}

或者只是

  while ( ( a = 10 ) );

或者更简单:

while ( a != 0 );

因为重要的是在 while 循环中变量 a 确实变为等于 0。

,
      while (1) {
          if (!(a=10)) {
              break;
          } 
      }

由于 !(a = 10) 始终为零(假),因此等效于:

      while (1) {
      }