当我尝试在 printf() 内部执行此操作时,它会取消对第三个元素的引用,我还尝试使用后增量和预增量来取消对该指针的引用。
这是我的代码:
#include <stdio.h>
int main()
{
int arr[4] = {1, 2, 3, 4};
int *ptr = &arr[0];
printf("ptr = %p, &arr[0] = %p\n", ptr, &arr); // same addrs
printf("*ptr = %d\n", *ptr); // 1, as expected
// PROBLEM IS HERE:
printf("%d, %d, %d\n", *ptr, *ptr++, *++ptr); // 3, 2, 2
return 0;
}
我尝试过一些有趣的事情,例如将元素添加到数组中,将 printf 中的表达式顺序更改为, 但这给了我另一个令人困惑的答案:
*++ptr, *ptr++, *ptr // 3, 1, 1
但是,当我按顺序尝试 printfs 时,可以这么说:
printf("*ptr = %d\n", *ptr);
printf("*ptr++ = %d\n", *ptr++);
printf("*++ptr = %d\n", *++ptr);
一切都按预期进行。
我对最后一个 printf 中的初始脚本的期望:
那么,为什么我得到了3、2、2?
你的程序正在调用未定义的行为,这意味着任何事情都可能发生,因此你不能依赖任何特定的行为。实际发生的情况可能取决于几个因素,例如您使用的编译器、编译器的版本、编译器使用的设置等。
行为未定义的原因是因为 ISO C11 标准§6.5 ¶2 规定了以下内容:
如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是无序的,则该行为是未定义的。在您的程序中,在
printf
的各个参数的评估之间不存在 序列点
。其中两个参数(
*ptr++
和
*++ptr
)会更改
ptr
的值(作为副作用),另外一个参数计算
ptr
的值。因此,根据上面引用的 ISO C 标准的段落,您的程序的行为是未定义的。请参阅此相关问题以获取更多信息: