++i和i++的区别(从汇编代码角度解释)

文章通过对比C语言中i++和++i在函数testi和testj中的实现,展示了它们在汇编层面的区别。++i先加后赋值,而i++后加前赋值,导致i++在汇编代码中多了一次内存访问,可能带来微小的性能差异。但在不做赋值的情况下,两者在汇编代码中表现相同。
摘要由CSDN通过智能技术生成

++i和i++的功能

void test(int i)
{
//假设此时传入参数i = 0
	int a = ++i;//执行完这行代码后,a = 1,i = 1
	int b = i++;//b = 1,i = 2
}

简而言之,++i是先+1再2赋值,i++是赋值完再+1

从汇编角度看两者的差异

准备工作

  1. 编写一段功能简单的程序test.c 如下:
#include<stdio.h>

void testi(int i){
    int a = i++;
}

void testj(int j){
    int a = ++j;
}


int main()
{
    int i = 0;
    int j = 0;
    testi(i);
    testj(j);
}
  • 使用gcc编译它
    gcc -o test test.c
  • 使用objdump命令反汇编并重定向到.asm文件中
    objdump -d test > test.asm

分析汇编代码

由上一步骤得到的.asm文件过长,此处不再一一展示,只选取最重要的部分

0000000000001129 <testi>:
    1129:	f3 0f 1e fa          	endbr64 
    112d:	55                   	push   %rbp
    112e:	48 89 e5             	mov    %rsp,%rbp
    1131:	89 7d ec             	mov    %edi,-0x14(%rbp)
    1134:	8b 45 ec             	mov    -0x14(%rbp),%eax
    1137:	8d 50 01             	lea    0x1(%rax),%edx
    113a:	89 55 ec             	mov    %edx,-0x14(%rbp)
    113d:	89 45 fc             	mov    %eax,-0x4(%rbp)
    1140:	90                   	nop
    1141:	5d                   	pop    %rbp
    1142:	c3                   	retq   
0000000000001143 <testj>:
    1143:	f3 0f 1e fa          	endbr64 
    1147:	55                   	push   %rbp
    1148:	48 89 e5             	mov    %rsp,%rbp
    114b:	89 7d ec             	mov    %edi,-0x14(%rbp)
    114e:	83 45 ec 01          	addl   $0x1,-0x14(%rbp)
    1152:	8b 45 ec             	mov    -0x14(%rbp),%eax
    1155:	89 45 fc             	mov    %eax,-0x4(%rbp)
    1158:	90                   	nop
    1159:	5d                   	pop    %rbp
    115a:	c3                   	retq   

应当明白,程序中的栈是向上增长的,即栈底的内存地址大于栈顶的内存地址
此处说明几个寄存器的作用:

  • %rsp:栈指针
  • %edi:传入的第一个参数所存储的通用寄存器。程序例子中只有一个参数,因此使用这个寄存器
  • %rax:存放临时变量

在汇编代码中,%eax就是变量a,又因为栈的向上增长,因此这里对栈基址做减法
mov %edi,-0x14(%rbp)
此时传入的参数就存储在-0x14(%rbp)这个内存地址中。
对比testi和testj,可以看到testi部分多了一个%edx寄存器,由于在+1前需要先赋值给变量a,因此%edx用于存储+1后的数据,再回送到-0x14(%rbp)中。而在testj中,由于是先+1再赋值,因此可以直接对着内存地址-0x14(%rbp)+1,再使用mov指令将其传送给%eax。最后,两个函数都将%eax的值传送给内存地址-0x4(%rbp)处。
可以看到,在汇编代码中,i++访问了5次内存,比++i多了1次。因此i++比++i更加耗时。
但是,如果仅仅做i++或者仅仅做++i的操作而不将其赋值给任何变量,在汇编代码中,两者的代码是一样的,可以简单编写程序求证。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值