C和Java的逻辑差异

par*_*ain 35 c c++ java operators

在C中编译并运行此代码

#include <stdio.h>

int main()
{
  int a[] = {10, 20, 30, 40, 50};
  int index = 2;
  int i;

  a[index++] = index = index + 2;
  for(i = 0; i <= 4; i++)
    printf("%d\n", a[i]);
}
Run Code Online (Sandbox Code Playgroud)

输出: 10 20 4 40 50

现在用于Java中的相同逻辑

class Check
{

  public static void main(String[] ar)
  {
    int a[] = {10, 20, 30, 40, 50};
    int index = 2;

    a[index++] = index = index + 2;
    for(int i = 0; i <= 4; i++)
      System.out.println(a[i]);
  }
}
Run Code Online (Sandbox Code Playgroud)

输出: 10 20 5 40 50

为什么两种语言都有输出差异,输出可以理解,Java但我无法理解输出C

还有一件事,如果我们应用前缀++运算符,我们在两种语言中得到相同的结果,为什么?

Pra*_*rav 64

那是因为a[index++] = index = index + 2;在C中调用未定义的行为.看看这个

从链接:

第二句话说:如果一个对象被写入一个完整的表达式,那么在同一个表达式中对它的任何和所有访问都必须直接参与计算要写入的值.此规则有效地将法律表达式约束为在修改之前明显存在访问的表达式.例如,允许旧备用i = i + 1,因为i的访问用于确定i的最终值.这个例子

 a[i] = i++
Run Code Online (Sandbox Code Playgroud)

是不允许的,因为i 的一个访问(a [i]中的一个)与最终存储在i中的值无关(在i ++中发生),所以没有好的方法来定义 -要么是我们的理解,要么是编译器 - 是否应该在存储增量值之前或之后进行访问.由于没有好的方法来定义它,标准声明它是未定义的,并且可移植程序根本不能使用这样的结构.与a[i++]=i(调用UB)类似,您的表达式也会调用UB.

您的表达式也有类似的行为.

行为定义明确Java.

  • +1 - 非常好的答案.你能添加一个关于Java定义内容的片段吗?只是为了好奇:-) (8认同)
  • @Topher:C和Java在这里有着截然不同的目标.C旨在使编译器能够很好地自由地提高性能,这与系统实现语言相似.Java旨在确定所有可能的行为,使程序员更容易.C和Java都非常成功. (3认同)
  • @Michiel:是的,那也是UB,同样的道理. (2认同)
  • `a [index ++] = index + 2`也是未定义的行为.可以这样想:标准表示增量在语句结束之前的某个时间发生,并且除此之外没有指定任何顺序.因此,无法知道增量是在添加之前还是之后发生.(它与`++ index`相同 - 而下标值是原始的`index + 1`,它的定义是什么时候实际存储到`index`中.)委员会选择调用这个未定义而不是未指定的标准,意味着任何行为都是合法的. (2认同)