suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Warum ändert sich der Wert des Zeigers auf diese Weise, wenn die printf-Funktion der C/C++-Sprache den Wert des Arrays ausgibt, auf das der Zeiger zeigt?

1. Die Parameter der prinf-Funktion enthalten Zeigerausdrücke. In welcher Reihenfolge werden sie offensichtlich nicht von links nach rechts berechnet?

#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;
}

大家讲道理大家讲道理2777 Tage vor1557

Antworte allen(4)Ich werde antworten

  • 给我你的怀抱

    给我你的怀抱2017-06-27 09:20:57

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

    Antwort
    0
  • 学习ing

    学习ing2017-06-27 09:20:57

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

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

    而 i++ 表示的是

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

    Antwort
    0
  • 某草草

    某草草2017-06-27 09:20:57

    函数参数的运算顺序,跟函数的内部逻辑关系不大,应该是入栈前(函数执行前)先计算++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)
        movl    $2, 44(%esp)
        movl    $3, 48(%esp)
        movl    $4, 52(%esp)
        movl    $5, 56(%esp)
        leal    40(%esp), %eax
        movl    %eax, 60(%esp)
        movl    60(%esp), %eax
        movl    (%eax), %eax
        movl    %eax, 4(%esp)
        movl    $LC0, (%esp)
        call    _printf
        movl    60(%esp), %eax
        movl    (%eax), %ebx
        movl    60(%esp), %eax
        leal    4(%eax), %edx
        movl    %edx, 60(%esp)
        movl    (%eax), %ecx
        movl    60(%esp), %eax
        movl    (%eax), %edx
        addl    $4, 60(%esp)
        movl    60(%esp), %eax
        leal    4(%eax), %esi
        movl    %esi, 60(%esp)
        movl    (%eax), %eax
        movl    %ebx, 16(%esp)
        movl    %ecx, 12(%esp)
        movl    %edx, 8(%esp)
        movl    %eax, 4(%esp)
        movl    $LC1, (%esp)
        call    _printf
        call    ___getreent
        movl    4(%eax), %eax
        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

    Antwort
    0
  • ringa_lee

    ringa_lee2017-06-27 09:20:57

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

    Antwort
    0
  • StornierenAntwort