为什么C语言的for循环条件可以接受初始化?

7

昨天我参加了一次面试,在那里我看到了一些奇怪的程序片段。

初步看来,我认为这个片段有编译错误。但是当我回家后手动在C编译器中尝试时,发现我完全错了。

看看面试代码:

#include<stdio.h>

void main()
{
   for(int i=0;i=5;i=5)// here condition and increment are assigned 
                       //wrongly and where I thought it is compilation 
                       //error during interview which isn't wrong
   {
      printf("helloworld \n");
   }
}

输出:

 helloworld
 helloworld
 helloworld
 helloworld
 helloworld
 helloworld
 .
 .
 .
 .(goes on and on)

C++中的输出类似于C语言。

但是,当我们在Java编译器中运行此代码时,

public class Forhottest {

public static void main(String args[])
{
    for(int i=0;i=5;i=5)// here it throws compilation error
    {
        System.out.println("helloworld");
    }
}

}

同样,我在PHP中尝试过,与Java中一样出现了同样的问题。 为什么C和C ++允许在“for循环”内部使用这种奇怪的条件语句? 这背后的原因是什么?

7
你为什么认为这应该是C语言的编译错误?如果不知道你的困惑根源在哪里,就无法正确解决问题。你为什么认为条件语句是“错误”的?它有什么问题? - AnT stands with Russia
4
C和Java是不同语言,有不同的规则。在C中,for循环语句中的测试表达式只需要是整数类型,而i=5就是一个整数类型。而在Java中,测试表达式必须是布尔类型,而i=5则不是。从语义上讲,C代码并没有错误,尽管它不太清晰;它既可以是等同于模糊的 for(;;) ,也可以代表常见的打字错误(使用=时应该使用==)。 - John Bode
2
你对面试官说了什么关于 void main() 的问题? - Weather Vane
@AnT 我是一个初学者,对不起我很无知。 - Srini
@WeatherVane 这是什么意思? - Srini
@JohnBode 谢谢您,现在我明白了。 - Srini
6个回答

9
在C和Java中,for循环的第二个组件是一个表达式,而赋值也是表达式。这就是为什么你可以(从语法上讲)有以下表达式的原因:
i = 5

作为 for 循环中的循环条件,两种语言都可以使用。然而,与 C 不同,Java 在 for 循环的静态语义定义中添加了以下行:表达式必须具有布尔类型或 Boolean 类型,否则将出现编译时错误。在 Java 中,表达式的类型
i = 5

Java编译器会报错,因为它的数据类型是int而不是boolean

C语言没有这个限制,它更倾向于在类型方面更加宽松,整数和布尔值可以看作是“相同的东西”。细节有点技术性,但整数5会被隐式地强制转换为真值,所以你会看到一个无限循环。


6

false(在C语言中)对应的是0。在C语言中,任何不为0的都被视作true。而Java则不同(Java具有强类型,不允许将int隐式转换为boolean)。因此,在Java中,相当于这样:

public static void main(String args[]) {
    for (int i = 0; (i = 5) != 0; i = 5)
    {
        System.out.println("helloworld");
    }
}

这会导致一个无限循环打印“helloworld”。


1
0.0 不是 0,但仍然与之相等,并表示“假”。 - Ruslan
@Ruslan printf("%d\n", 0==0.0); @Ruslan printf("%d\n", 0==0.0); - Elliott Frisch
1
这并不否定我所说的:“printf(“%d \ n”,!! 0.0);”。 - Ruslan

4

因为在C语言中,赋值语句是表达式而不是语句。这点在不同的编程语言中是不同的...

注意:要始终阅读编译器的警告,并使用-Wall -Wextra -Werror -pedantic -pedantic-errors来避免此类笔误。如果您阅读了警告,您的void main()也无法通过编译。

正如Ray Toal在Java中指出的那样,赋值也是表达式,但是整数不会自动转换为布尔值。


2
在Java中...整数不会自动转换为布尔值,这是这个答案中唯一重要的部分。 - Paul Ogilvie

1

在Java中,对于FOR循环

for(int i=0;i=5;i=5)

所示代码(for循环的中间条件)期望是布尔类型。你不能使用不返回布尔值的表达式。

Java是一种强大的语言,每个东西都是强类型的。在C/C++中,将i=5赋值是可以的,因为该表达式会转换为bool值true,但是在Java编译器中,这个操作会抛出错误无法从int转换为boolean


1
你的意思是在那里不能给出一个“整数表达式”。干杯。 - Ray Toal

0

好的,让我们分解一下代码在做什么。

你有:

for(int i=0;i=5;i=5)// here condition and increment are assigned wrongly and where I thought it is compilation during interview
{
    printf("helloworld \n");
}

在C语言中,for(int i=0;i<=5;i++)中的每个部分都是一个表达式。 请记住,for循环只是while循环的一种语法糖。
这段话的翻译如下:
int i=0;
while( i=5 ) {
    printf("helloworld \n");
    i=5;
}

Java抱怨的原因是因为Java比C和C++具有更强的类型。在Java中,中间表达式被期望是一个严格的bool值/结果才能被认为是有效的Java。

在C(++)中,布尔值只是整数值(true == 1 and false == 0)。 赋值被视为一个表达式,如果你给一个标识符的值大于或小于0,则该表达式将评估为true。

让我们在另一种情况下使用它!

int main()
{
    int i;
    if( i = -1, i=5 )   // this would run
        printf("Hello World\n");
}

0

i=5 的值为 5(int j=i=5; 是有效的,且 j == 5)。在 C 和 C++ 中,5 是“真”值。Java 和 Php 在 for 循环的第二个参数中期望一个布尔值,而 C 和 C++ 则接受整数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接