为什么同样的代码在C和Java中表现不同?

3
在C语言中,以下代码片段为例:
int i;
    double x[10];
    for (i = 0; i <= 10; i++) {
        x[i] = (double) i;
        printf("%f\n", x[i]);
    }

产生以下输出:
0.000000
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
9.000000
10.000000

然而,在Java中,这段代码片段(相同的代码)只是语法上有所不同:

int i;
        double[] x = new double[10];
        for (i = 0; i <= 10; i++) {
            x[i] = (double) i;
            System.out.printf("%f\n", x[i]);
        }

产生以下输出:
0.000000
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
9.000000
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
    at Array.main(Array.java:14)

为什么C编译器没有检测到访问超出数组边界的尝试呢?难道我漏掉了什么重要的东西吗?

在这两种情况下,都不是编译器检查边界。这发生在运行时(在Java中),或根本不发生(在C中)。 - Thilo
你的循环应该从0到9工作。 - Himanshu
请参见https://dev59.com/SlvUa4cB1Zd3GeqPrj9P。 - Lundin
这个问题明确询问了C++,而不是像重复的那个问题询问C和Java之间的区别。重复的问题只是部分地、间接地回答了这个问题。我投票支持重新开放。 - juanchopanza
2个回答

6
Java有数组边界检查,而C没有。在Java中,当您访问索引10时,会出现运行时异常,在C中则会出现未定义的行为。在这种情况下,您将10.0写入了不允许的位置,但由于纯粹的运气,程序仍能正常运行完成。
另外请注意,Java数组有一个“length”属性,可以轻松避免这种错误。在C的情况下,可以通过仔细使用“sizeof”运算符来获取数组的长度。但通常情况下,指针而不是数组被使用(例如,当您将数组“传递”给接受数组元素指针的函数时),因此往往难以获得大小信息。

当你写代码时,除了你要覆盖的具体内容之外,它是否真的是未定义的? - Thilo
1
@Thilo 是的,它是未定义的。如果不添加边界检查系统的开销,很难指定在这种情况下应该发生什么。 - juanchopanza

0

在 C 语言中,我们可以访问未初始化的变量元素。但在 Java 中,我们不能这样做。它会严格检查数组边界。

每次访问数组中的元素时,Java 都会执行边界检查。边界检查是指将对数组索引的访问与数组大小进行比较 - 如果该数组索引超出了边界并且大于数组的大小,则会抛出异常。

C 不执行边界检查。


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