【问题标题】:Output of expression ++a,a,a-- in C & Java [duplicate]C和Java中表达式++a,a,a--的输出[重复]
【发布时间】:2019-11-23 01:08:29
【问题描述】:

我正在评估代码并在 C 和 Java 中获得不同的输出。 由于它是一个表达式,因此必须在两种语言中生成相同的输出。但跑步时就不是这样了。

以下是代码示例和更多说明

C:

案例一:

    int a=101;
    printf("%d,%d", ++a,a);

输出= 102,102

案例 2:

   int a=101;
    printf("%d,%d,%d", ++a,a,a--);

输出 = 101,101,101

Java:

    int a=101;
    System.out.print( ++a +"," + a + "," + a--);

输出 = 102,102,102

对于像 Java 这样的 C 语言中的第二种情况,我希望输出为 102,102,102。但是输出是 101,101,101

【问题讨论】:

  • 在 C 中,即undefined behavior
  • “因为它是一个表达式,所以必须在两种语言中生成相同的输出”不正确
  • 每个问题应该问一个问题。是的,您的第一个假设存在严重缺陷:两种语言允许相同的语法这一事实并不意味着语义相同。德语单词 pass 的写法类似于英语的“pass”,但在这两种不同的语言中它们的含义不同!
  • 有关这些 C 表达式的完整故事,请参阅this canonical question and answer

标签: java c operators increment decrement


【解决方案1】:

既然是表达式,……

这是错误的。正如您在printf("%d,%d", ++a,a); 中使用的++a,a,它们是函数调用的两个独立参数,不构成一个表达式。

因为它是一个表达式,所以必须在两种语言中生成相同的输出。

这是错误的。 C 和 Java 有不同的表达式求值规则。

printf("%d,%d", ++a,a);

这违反了 C.C 2018 6.5 2 中的一条规则:

如果标量对象的副作用相对于同一标量对象的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义......

printf("%d,%d", ++a,a); 中,++ 运算符具有递增a 的副作用,第二个a 是使用a 的值进行值计算。 C 的规则没有说明副作用和值计算将按什么顺序发生,因此它们相对于彼此是无序的。因此,行为未定义。

【讨论】:

    【解决方案2】:

    C 和 Java 在这方面的表现非常不同。

    C 代码遇到了两个问题:

    • C 不会强制对函数参数进行特定的求值顺序 - 不要假设它们是从左到右求值的。分隔函数参数的逗号不是逗号运算符

    • ++ 运算符可能不会在计算表达式后立即应用副作用。在 x = a++ * ++b 这样的表达式中,ab 的更新可能要等到分配给 x 之后才会发生。

    C 语言定义明确地将这种代码称为未定义行为,这意味着编译器不需要以任何特定方式处理这种情况。几乎任何结果都是可能的。

    【讨论】:

    • 几乎所有结果,包括没有成功编译程序
    【解决方案3】:

    据我所知,在 C 语言中,逗号是二元运算符(就像 +、-、*、/ 一样),乍一看有一些奇怪的行为。 它确实评估逗号的左侧并丢弃它的结果并分配右侧。 也许这个例子会很清楚:

    int a=1;
    int b=2;
    int c=(a,b); //will assign c to 2
    

    在我们的脑海中,你需要这个表达式,就像编译器最有可能看到的那样。大概是这样的:

    (STRING,(++a,(a,a--)))
    

    如果您通过 left-discard-right-assign 逻辑来执行此语句,则结果将是a,然后才会递减。因此,如果您有一个 printf 打印 a 在此之后 a 最终应该是 100。

    如果你想进一步看这个,这个wikipedia-article应该没问题。


    注意:逗号的偏好非常低

    【讨论】:

    • 函数中用来分隔参数的逗号是不是的逗号操作符。函数参数不按任何特定顺序计算,也不引入序列点。
    【解决方案4】:

    看,在第一种情况下:-

    我们正在初始化一个整数类型的变量,其值为 101 ... 我们正在打印 ++a 和 a ...

    ++a 表示它是前自增运算符,a++ 是后自增运算符

    工作:-

    考虑一个值为 101 的盒子 ... ++a 表示 preincrement 运算符,首先增加 value 并在框中更新 然后打印该值(值到框中...)

    而a++表示后自增运算符,它先打印框中的值,然后增加框中的值,然后更新框中的值

    减量也一样

    以防万一:-

    a=101 我们正在打印 ++a 和 a ...

    现在考虑一个值为 101 的盒子... ++a 将首先增加值意味着它变为 102 并将 102 值更新到 a 的框中... 现在,一个盒子里有102个 然后就没有操作了……

    所以一个盒子包含 102 ...

    所以它将打印 102 , 102 作为输出 ...

    情况2:-

    a=101 我们正在打印 ++a , a , a--

    所以考虑一个包含值 101 的盒子 ....

    在这种情况下,如果有两个以上的运算符,则先求解括号

    (++a,(a,a--))

    第一个操作是 a ,框 a 中的值将保持不变...

    现在,框 a 中的值将是 101 表示保持不变

    下一个操作是 a-- ,它会将框 a 中的值递减为 100 ..并更新框中的值

    现在 a 框中的值将是 100

    下一个操作是 ++a ,因此它将值递增到 a 的框中。 首先

    现在输入框 a 的值将是 101 .... 再次

    它将打印 101 , 101 , 101 作为输出 ....

    我不会启动 java ...因为我不会给你 java 的 ans ...

    【讨论】:

      猜你喜欢
      • 2013-12-16
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 2011-08-26
      • 2014-12-05
      • 2021-05-09
      • 2015-07-29
      • 2017-01-30
      相关资源
      最近更新 更多