计算两个全局变量间的偏移

本文探讨了编译器如何优化地址计算过程,特别是在处理不同类型的变量时所采取的方法。通过对比两个相似代码片段的汇编输出,解释了编译器是如何通过除以类型大小来简化内存地址计算的,并强调了理解编译器行为对于编写高效代码的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 #include <stdio.h>
2
3 int start = 1;
4 int end = 2;
5 int a()
6 {
7 int off;
8 off = &end - &start;
9 printf("%d\n",off);
10 }
11
12 int main()
13 {
14 a();
15 }

root@ubuntu:~# ./test_length
1 ------------------------------->结果有误

root@ubuntu:~# objdump -D test_length
080483c4 <a>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 ec 28 sub $0x28,%esp
80483ca: ba 18 a0 04 08 mov $0x804a018,%edx
80483cf: b8 14 a0 04 08 mov $0x804a014,%eax
80483d4: 89 d1 mov %edx,%ecx
80483d6: 29 c1 sub %eax,%ecx
80483d8: 89 c8 mov %ecx,%eax
80483da: c1 f8 02 sar $0x2,%eax ;这边右移了两位,相当于除以4
80483dd: 89 45 f4 mov %eax,-0xc(%ebp)
80483e0: b8 d0 84 04 08 mov $0x80484d0,%eax
80483e5: 8b 55 f4 mov -0xc(%ebp),%edx
80483e8: 89 54 24 04 mov %edx,0x4(%esp)
80483ec: 89 04 24 mov %eax,(%esp)
80483ef: e8 00 ff ff ff call 80482f4 <printf@plt>
80483f4: c9 leave
80483f5: c3 ret

1 #include <stdio.h>
2
3 int start = 1;
4 int end = 2;
5 int a()
6 {
7 int off;
8 off = (char *)&end - (char *)&start;
9 printf("%d\n",off);
10 }
11
12 int main()
13 {
14 a();
15 }

root@ubuntu:~# ./test_length
4 ------------------------------>结果正确

root@ubuntu:~# objdump -D test_length
080483c4 <a>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 ec 28 sub $0x28,%esp
80483ca: ba 18 a0 04 08 mov $0x804a018,%edx
80483cf: b8 14 a0 04 08 mov $0x804a014,%eax
80483d4: 89 d1 mov %edx,%ecx
80483d6: 29 c1 sub %eax,%ecx
80483d8: 89 c8 mov %ecx,%eax ;此处就没有进行除以4,编译器优化了char的没有必要除1了
80483da: 89 45 f4 mov %eax,-0xc(%ebp)
80483dd: b8 d0 84 04 08 mov $0x80484d0,%eax
80483e2: 8b 55 f4 mov -0xc(%ebp),%edx
80483e5: 89 54 24 04 mov %edx,0x4(%esp)
80483e9: 89 04 24 mov %eax,(%esp)
80483ec: e8 03 ff ff ff call 80482f4 <printf@plt>
80483f1: c9 leave
80483f2: c3 ret


由上可以发现,编译器再计算时,会对地址处理为length/sizeof(type),所以要转换为char *的地址类型

转载于:https://www.cnblogs.com/moonflow/archive/2012/09/24/2700621.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值