C/C++语言printf函数输出指针指向的数组的值时,指针的值为什么这样变化?

发布于 2022-09-05 02:48:34 字数 405 浏览 14 评论 0

1.请问prinf函数的参数中含有指针表达式,是按照什么顺序运算的,代码运算结果中显然不是从左到右进行的。

#include <stdio.h>
int main() {
    int a[5] = { 1,2,3,4,5 };
    int *p = a;
    printf("%d\n", *p);
    printf("%d %d %d %d\n", *(++p)++,*p, *p++, *p);

    getchar();
    return 0;
}

图片描述

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风情万种。 2022-09-12 02:48:35

printf{"%d",++i} 表示两个操作

先执行i=i+1,再输出i

而 i++ 表示的是

先输出后,再执行 i=i+1

荒岛晴空 2022-09-12 02:48:35

函数参数的运算顺序,跟函数的内部逻辑关系不大,应该是入栈前(函数执行前)先计算++p,函数结束后,再计算p++。如果想知道具体的顺序,可以参照汇编代码(具体含义参考注释)

    .file    "a.cpp"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC0:
    .ascii "%d\12\0"
LC1:
    .ascii "%d %d %d %d\12\0"
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB10:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    pushl    %esi
    pushl    %ebx
    andl    $-16, %esp
    subl    $64, %esp
    .cfi_offset 6, -12
    .cfi_offset 3, -16
    call    ___main
    movl    $1, 40(%esp)     ;从(esp+40)到(esp+56)间,依次放入1~5。int a[5] = { 1,2,3,4,5 };
    movl    $2, 44(%esp)
    movl    $3, 48(%esp)
    movl    $4, 52(%esp)
    movl    $5, 56(%esp)
    leal    40(%esp), %eax   ;(esp+40)的地址,放入(esp+60)。int *p = a;
    movl    %eax, 60(%esp)
    movl    60(%esp), %eax   ;从(esp+60)地址中取值,放入eax。*p
    movl    (%eax), %eax
    movl    %eax, 4(%esp)    ; printf参数2, eax(即*p)
    movl    $LC0, (%esp)     ; printf参数1, "%d\12\0"
    call    _printf          ; 调用printf
    movl    60(%esp), %eax   ; 从(esp+60)地址中取值,放入ebx(即*p)
    movl    (%eax), %ebx
    movl    60(%esp), %eax   ; 把(esp+60)的值放入eax
    leal    4(%eax), %edx    ; eax中记录的地址+4的值,放入edx(即*(++p))
    movl    %edx, 60(%esp)   ; 把edx的值,放入(esp+60)
    movl    (%eax), %ecx     ; 从eax记录的原(esp+60)地址中的值,放入ecx(即*p)
    movl    60(%esp), %eax   ; 从(esp+60)地址中取值,放入edx
    movl    (%eax), %edx
    addl    $4, 60(%esp)     ; (esp+60)的值+4,放入eax(即eax=*(p+2))
    movl    60(%esp), %eax   ; 从(esp+60)地址中取值,+4后的地址放入esi
    leal    4(%eax), %esi
    movl    %esi, 60(%esp)   ; 把esi的值,放入(esp+60),
    movl    (%eax), %eax     ; eax = *eax
    movl    %ebx, 16(%esp)   ; printf参数5, %ebx(即*p)
    movl    %ecx, 12(%esp)   ; printf参数4, %ecx(即*p)
    movl    %edx, 8(%esp)    ; printf参数3, %edx(即*(++p))
    movl    %eax, 4(%esp)    ; printf参数2, %eax(即*(p+2))
    movl    $LC1, (%esp)     ; printf参数1, "%d %d %d %d\12\0"
    call    _printf
    call    ___getreent
    movl    4(%eax), %eax    ; 把*(eax+4)的放入*esp
    movl    %eax, (%esp)
    call    _getc
    movl    $0, %eax
    leal    -8(%ebp), %esp
    popl    %ebx
    .cfi_restore 3
    popl    %esi
    .cfi_restore 6
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE10:
    .ident    "GCC: (GNU) 5.4.0"
    .def    _printf;    .scl    2;    .type    32;    .endef
    .def    ___getreent;    .scl    2;    .type    32;    .endef
    .def    _getc;    .scl    2;    .type    32;    .endef

题外话:
结果中出现的2和3还可以说的通。
4很奇怪,非要勉强地解释的话,*(++p)++括号外面的++也对p起作用了,
但是形如p++运算符,应该在语句结束后才自增的,所以这样解释明显不对。
我在Cygwin + gcc (GCC) 5.4.0环境,运行的结果如下,没有出现4。

1
3 2 1 1

请问题主用了什么环境?如果有汇编代码的话,贴出来可以一起分析下。

浅沫记忆 2022-09-12 02:48:34

在一条语句里多次改变一个变量属于未定义行为,在不同平台可能有不同结果。这个问题没有意义。

我不吻晚风 2022-09-12 02:48:34

函数参数压栈的顺序是一定的,只是参数的求值顺序是未指定的,
编译器只保证在printf调用之前,所有参数的值是已知的
这方面的资料可以搜索序列点(Sequence Point)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文