char * p =“你好”; printf(“%c%c%c%c”,* p,* ++ p,* p ++,* p);

时间:2014-02-20 16:04:01

标签: c pointers

char* p = "hello"; printf(" %c %c %c %c", *p, *++p, *p++, *p);

输出:

l l h h 

我已经阅读了下面的帖子,但仍然无法找到为什么输出就像“l l h h”。谁能请回答。

Pointer expressions: *ptr++, *++ptr and ++*ptr

3 个答案:

答案 0 :(得分:2)

由于代码同时包含++pp++,因此会尝试修改p两次。

这些表达式出现在函数调用的参数中。 C标准没有指定评估函数参数的顺序。

当程序尝试以无序方式修改对象两次时,程序将被破坏。 C 2011标准在第6.5条第2款中说,当对同一对象进行两次无序修改时,C标准不对该程序的行为施加任何要求。

这意味着编译器不必以任何特定方式使该程序工作。编译器基本上“放弃”并做任何事情。

答案 1 :(得分:1)

这会调用未定义的行为。您可能会收到预期或意外结果或程序崩溃或分段错误等 printf的参数评估顺序未定义。它们可以按任何顺序进行评估,并导致 p在两个序列点内多次修改。这会调用UB c-faq: 3.8

  

在上一个和下一个序列点之间,对象的存储值最多只能通过表达式的修改一次修改。此外,只能访问先前值以确定要存储的值。

答案 2 :(得分:-1)

评估顺序未定义,因此您不应该依赖于一个参数中的副作用来获取另一个参数的值。

在您的示例中,看起来参数是从右到左计算的,这反映了printf函数的调用约定,其中第一个参数位于堆栈的顶部。像printf这样支持变长参数列表的方法利用了这一点,因为编译器将发出信息,允许函数以从左到右的顺序遍历参数列表。

C支持许多不同的调用约定。 C调用约定从右到左推送参数,但Pascal调用约定从左到右。其他将一些参数放入寄存器并将其余参数传递给堆栈。通过不强制执行评估顺序,语言在处理这些调用约定时为编译器提供了更大的灵活性。