C语言高级编程:i++ 或 ++i作为函数参数

测试机:Ubuntu14.04 x86_64

1. 代码:

#include <stdio.h>

void print(int a, int b, int c)
{
    printf("a = %d\n", a);
    printf("b = %d\n", b);
    printf("c = %d\n", c);
}

void main(void)
{
    int para1 = 5;
    int para2 = 6;
    int para3 = 7;

    print(para1++, ++para2, para3);

    printf("a = %d\n", para1);
    printf("b = %d\n", para2);
    printf("c = %d\n", para3);
}

2. 结果:

baoli@ubuntu:~/c$ ./a.out
a = 5
b = 7
c = 7
a = 6
b = 7
c = 7

3. 反汇编:

000000000040052d <print>:
  40052d:    55                       push   %rbp
  40052e:    48 89 e5                 mov    %rsp,%rbp
  400531:    48 83 ec 10              sub    $0x10,%rsp
  400535:    89 7d fc                 mov    %edi,-0x4(%rbp)
  400538:    89 75 f8                 mov    %esi,-0x8(%rbp)
  40053b:    89 55 f4                 mov    %edx,-0xc(%rbp)

  40053e:    8b 45 fc                 mov    -0x4(%rbp),%eax
  400541:    89 c6                    mov    %eax,%esi
  400543:    bf 84 06 40 00           mov    $0x400684,%edi
  400548:    b8 00 00 00 00           mov    $0x0,%eax
  40054d:    e8 be fe ff ff           callq  400410 <printf@plt>
  400552:    8b 45 f8                 mov    -0x8(%rbp),%eax
  400555:    89 c6                    mov    %eax,%esi
  400557:    bf 8c 06 40 00           mov    $0x40068c,%edi
  40055c:    b8 00 00 00 00           mov    $0x0,%eax
  400561:    e8 aa fe ff ff           callq  400410 <printf@plt>
  400566:    8b 45 f4                 mov    -0xc(%rbp),%eax
  400569:    89 c6                    mov    %eax,%esi
  40056b:    bf 94 06 40 00           mov    $0x400694,%edi
  400570:    b8 00 00 00 00           mov    $0x0,%eax
  400575:    e8 96 fe ff ff           callq  400410 <printf@plt>

  40057a:    c9                       leaveq
  40057b:    c3                       retq   


000000000040057c <main>:
  40057c:    55                       push   %rbp
  40057d:    48 89 e5                 mov    %rsp,%rbp
  400580:    48 83 ec 10              sub    $0x10,%rsp
  400584:    c7 45 f4 05 00 00 00     movl   $0x5,-0xc(%rbp)
  40058b:    c7 45 f8 06 00 00 00     movl   $0x6,-0x8(%rbp)
  400592:    c7 45 fc 07 00 00 00     movl   $0x7,-0x4(%rbp)

  400599:    83 45 f8 01              addl   $0x1,-0x8(%rbp)
  40059d:    8b 45 f4                 mov    -0xc(%rbp),%eax
  4005a0:    8d 50 01                 lea    0x1(%rax),%edx
  4005a3:    89 55 f4                 mov    %edx,-0xc(%rbp)
  4005a6:    8b 55 fc                 mov    -0x4(%rbp),%edx
  4005a9:    8b 4d f8                 mov    -0x8(%rbp),%ecx
  4005ac:    89 ce                    mov    %ecx,%esi
  4005ae:    89 c7                    mov    %eax,%edi
  4005b0:    e8 78 ff ff ff           callq  40052d <print>

  4005b5:    8b 45 f4                 mov    -0xc(%rbp),%eax
  4005b8:    89 c6                    mov    %eax,%esi
  4005ba:    bf 84 06 40 00           mov    $0x400684,%edi
  4005bf:    b8 00 00 00 00           mov    $0x0,%eax
  4005c4:    e8 47 fe ff ff           callq  400410 <printf@plt>
  4005c9:    8b 45 f8                 mov    -0x8(%rbp),%eax
  4005cc:    89 c6                    mov    %eax,%esi
  4005ce:    bf 8c 06 40 00           mov    $0x40068c,%edi
  4005d3:    b8 00 00 00 00           mov    $0x0,%eax
  4005d8:    e8 33 fe ff ff           callq  400410 <printf@plt>
  4005dd:    8b 45 fc                 mov    -0x4(%rbp),%eax
  4005e0:    89 c6                    mov    %eax,%esi
  4005e2:    bf 94 06 40 00           mov    $0x400694,%edi
  4005e7:    b8 00 00 00 00           mov    $0x0,%eax
  4005ec:    e8 1f fe ff ff           callq  400410 <printf@plt>
  4005f1:    c9                       leaveq
  4005f2:    c3                       retq   
  4005f3:    66 2e 0f 1f 84 00 00     nopw   %cs:0x0(%rax,%rax,1)
  4005fa:    00 00 00
  4005fd:    0f 1f 00                 nopl   (%rax)

4. 分析:

1. 对于para1++,先保存5到eax,后面会将eax保存到edi,所以edi也是5;然后再将值+1存到edx和rbp,所以edx和rbp都是6,由于在print中使用的是edi,所以打印是5

mov    -0xc(%rbp),%eax

lea    0x1(%rax),%edx

mov    %edx,-0xc(%rbp)

mov    %eax,%edi

2. 对于++para2,先+1,然后保存到ecx和esi,由于在print使用esi,所以打印是7

addl   $0x1,-0x8(%rbp)

mov    -0x8(%rbp),%ecx

mov    %ecx,%esi

3. 对于para3

mov    -0x4(%rbp),%edx

4. 对于下列结果,由于使用的都是rpb,所以都是自增后的值

a = 6    //mov    -0xc(%rbp),%eax

b = 7    //mov    -0x8(%rbp),%eax

c = 7

注:上述参数传递没有使用入栈的方式,而是直接使用了寄存器传(eax、ecx、edx、esi、edi)递变量值,速度更快。

5. 总结:

1) 函数参数尽量不要使用++的形式,容易混淆,如果必须使用,使用++i形式。

2)++i作为函数参数时,传入函数内部的是自增后的值; i++作为函数参数时,传入函数内部的是原值(自增前)

3)无论是++i还是i++最后都会使值加1

发布了170 篇原创文章 · 获赞 116 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/u012247418/article/details/102371022