You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何指向数组首元素的指针在printf中解引用后得到第三元素?

指针自增在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); // 地址相同
    printf("*ptr = %d\n", *ptr); // 输出1,符合预期

    // 问题出在这里:
    printf("%d, %d, %d\n", *ptr, *ptr++, *++ptr); // 实际输出3, 2, 2  

    return 0;
}

调整printf参数顺序为*++ptr, *ptr++, *ptr时,输出为3, 1, 1;但将三个操作拆分为三次独立的printf调用:

printf("*ptr = %d\n", *ptr);
printf("*ptr++ = %d\n", *ptr++);
printf("*++ptr = %d\n", *++ptr);

结果完全符合预期。原本预期第一个printf的输出为1, 1, 3,实际却得到3, 2, 2,该现象的原因如下:

原因解析

这是C语言中的未定义行为导致的。C标准并没有规定函数参数的求值顺序,编译器可以按照任意顺序计算printf的各个参数;同时,在同一个函数调用的参数列表中,对同一个变量(这里是ptr)进行多次修改和读取操作时,没有明确的序列点约束这些操作的执行顺序。

具体来说:

  • 对于printf("%d, %d, %d\n", *ptr, *ptr++, *++ptr),编译器可能先计算最右侧的*++ptr:ptr自增指向arr[1],解引用得到2;接着计算中间的*ptr++:先解引用当前ptr(指向arr[1])得到2,再将ptr自增指向arr[2];最后计算最左侧的*ptr:此时ptr已经指向arr[2],解引用得到3。这就解释了输出3, 2, 2的原因。
  • 调整参数顺序后,编译器的求值顺序变化,自然会得到另一组混乱的结果。

而拆分多次调用printf时,每次printf调用都是一个序列点:进入函数体前所有参数求值完成,函数调用结束后,后续代码的执行顺序明确。每次调用都会确保之前的修改操作完全生效,后续操作基于修改后的变量值执行,因此结果符合预期。

总结:在同一个函数调用的参数列表中,不要对同一个变量同时进行多次修改和读取操作,这类行为的结果不可预测,完全依赖编译器实现。

内容的提问来源于stack exchange,提问作者lil_robo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:47:15