1

谁能帮我理解下面代码的输出:

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 中处理(编译)赋值的见解。

4

2 回答 2

7

这是未指定的行为。C 标准中没有指定函数参数的求值顺序,因此它可以以任何顺序发生。

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

来自 C11 标准:

3.4.4:

  1. 未指定的行为
    使用未指定的值,或本国际标准提供两种或多种可能性并且在任何情况下都选择不强加进一步要求的其他行为

  2. 示例未指定行为的一个示例是计算函数参数的顺序。

6.5.2.2.10 说

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

换句话说,函数参数的求值之间没有序列点,因此它们可以按照编译器感觉的任何顺序进行求值。

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

6.5.2:

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

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

于 2012-07-31T09:06:23.067 回答
0
printf("%d %d %d %d %d",a--,a,a=20,a++,a=39);

这是未定义的行为

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

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

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

于 2012-07-31T09:31:35.397 回答