printf中的多个赋值语句c

时间:2012-07-31 09:04:19

标签: c compiler-construction printf

任何人都可以帮助我理解下面代码的输出:

int main()
{
    int a=35;
    printf("%d %d %d %d %d",a--,a,a=20,a++,a=39);
    return 0;
}

输出:20 19 19 39 19

了解如何在printf函数中的c中处理(编译)赋值。

2 个答案:

答案 0 :(得分:7)

这是未指明的行为。函数参数的评估顺序未在C标准中指定,因此可以按任何顺序发生。

人们已经在您可以阅读的评论中给了您一些链接。但总之,有一些叫做“序列点”的东西。这些确保了在执行之前需要执行的所有内容,然后程序可以继续执行。在两个序列点之间,指令可以按任何顺序执行。

来自C11标准:

3.4.4:

  
      
  1. 未指明的行为
      使用未指定的值或本国际标准提供的其他行为   两种或更多种可能性,并且没有任何进一步的要求   实例

  2.   
  3. 示例未指定行为的示例是评估函数参数的顺序。

  4.   

6.5.2.2.10说

  

在评估函数指示符和实际值之后有一个序列点   参数但在实际调用之前。调用函数中的每个评估(包括   其他函数调用)在其他方式之前或之后没有特别排序    被调用函数体的执行是相对于不确定地排序的   执行被调用的函数。

换句话说,在评估函数的参数之间没有序列点,因此可以按照编译器的顺序来评估它们。

要完成答案,这也是未定义的行为,因为您尝试在两个序列点之间多次更改a的值。

6.5.2:

  

如果对标量对象的副作用相对于同一标量对象的不同副作用或使用相同标量值的值计算未被排序   对象,行为未定义。如果表达式的子表达式有多个允许的排序,则如果在任何排序中发生这种未测序的副作用,则行为是不确定的。 84)

     

84)他的段落呈现未定义的语句表达式,例如
      i = ++i + 1;
      a[i++] = i;
  同时允许       i = i + 1;
      a[i] = i;

答案 1 :(得分:0)

printf("%d %d %d %d %d",a--,a,a=20,a++,a=39);

这是未定义的行为

这意味着该程序可以打印:20 19 19 39 190 0 0 0 0,甚至可以格式化您的硬盘。

  

(C99,6.5p2)“在上一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。

当然违反不是约束的“shall”意味着prgram调用未定义的行为(参见C99中的4.p2)。