2013-11-01 48 views
0
#include<stdio.h> 
int main() 
{ 
    int i=2; 
    printf("%d %d \n",++i,++i); 
} 

上面的代码给出了输出4 4。任何人都可以帮助解释输出吗?C中的printf()的意外工作

+1

这是未定义的行为。请参阅此处的示例 http://stackoverflow.com/questions/19694756/how-pre-and-postfix-are-evaluated-in-printf – jaap

回答

1

它与序列点有关,它可能导致未定义的行为。维基百科

直:一个函数在一个函数调用进入

之前。 参数评估的顺序没有指定,但是这个顺序点 意味着它们的所有副作用在输入函数 之前完成。

此处了解详情:http://en.wikipedia.org/wiki/Sequence_point

2

++ i是前缀增量。 Printf应该先打印它们的参数,然后再打印它们(尽管顺序无法保证,严格来说,未定义 - 请参阅未定义行为上的Wiki条目:http://en.wikipedia.org/wiki/Undefined_behavior)。

前缀增量被称为“增量和提取”,即它首先递增该值,然后将其提供给调用者。

在你的情况下,i第一次增加了两次,只有之后输出格式化并发送到控制台。

+0

此答案是如何得到投票的?在func(a,a ++)中,不是逗号运算符,它仅仅是参数a和++之间的分隔符。在这种情况下,行为是不确定的,如果a被认为是原始类型)' – Sadique

+0

@Acme我投了票,它根本没有提到逗号运算符?但它确实提到这只是一个函数调用,并且调用需要在进行实际调用之前评估其所有参数,这似乎是混淆OP的一点。 – unwind

+0

@unwind - 你在说什么和在答案中有细微的差别。答案是谈论评估的顺序是未指定的,这是正确的,但它没有提到它是UB。这'在你的情况下,我第一次增加了两次,然后才输出格式化并发送到控制台.'是不正确的。这个'printf(“%d%d \ n”,++ i,++ i);'是明确的UB。先评估一下这个''%d%d \ n“',这个'++ i'还是这个'++ i' - 考虑一下。 – Sadique

0

这两个答案都犯了同样的错误。它清晰的UB,而不仅仅是不明确的行为。

你所经历的是Undefined behavior。请阅读有关顺序点。逗号是函数调用中的分隔符,不是操作符。

一个序列点是一个时间点,在这个时间点,尘埃已经沉淀,并且迄今为止看到的所有副作用都保证完成。在C标准中列出的序列的要点是:

在一个完整表达式(全 表达式是一个表达式语句,或任何其他表达这 不是任何更大的表达式内的子表达式的评估的端部); at ||,& &,?:和逗号运算符;和 在一个函数调用(在评估所有参数之后,并且在实际调用之前)。

标准指出

之前和下一序列点之间的对象应具有由表达式的评估修饰的至多一次其 存储的值。 此外,只有在访问先前值时才能确定要存储的值。

什么将首先这"%d %d \n"评估,这++i或本++i(第二个) - 想想吧。在函数调用输入函数之前

:这将是不确定的行为:

void f(int x) 
{ 
    printf("%d ",x); 
} 
int main() 
{ 
    int i=0; 
    f(i++) ; 
} 

从维基。 参数评估的顺序没有指定,但是这个顺序点 意味着它们的所有副作用在输入函数 之前完成。在表达式f(i ++)+ g(j ++)+ h(k ++)中,f被称为 ,其参数为i的原始值,但i在进入f的主体之前增加 。类似地,j和k分别在 分别输入g和h之前更新。但是,并没有规定执行哪个命令f(),g(),h(),也不知道i,j,k的递增顺序。 f主体中的变量j和k可能已经或可能没有 已经增加。请注意,函数调用f(a,b,c)不是使用逗号运算符的 ,未指定a,b和c的评估顺序。