ibr*_*ead 14 c c++ arrays assembly pointers
c-faq告诉我,编译器在处理a [i]时做了不同的事情,而a是数组或指针.这是c-faq的一个例子:
Run Code Online (Sandbox Code Playgroud)char a[] = "hello"; char *p = "world";
鉴于上面的声明,当编译器看到表达式a [3]时,它会发出代码从位置"a"开始,移动三个,然后在那里获取字符.当它看到表达式p [3]时,它会发出代码从"p"位置开始,在那里获取指针值,向指针添加三个,最后获取指向的字符.
但有人告诉我,在处理[i]时,编译器倾向于将a(这是一个数组)转换为指向数组的指针.所以我想查看汇编代码以找出哪个是正确的.
编辑:
这是本声明的来源.c-faq 并注意这句话:
形式a [i]的表达式导致数组衰减成指针,遵循上面的规则,然后被下标,就像表达式p [i]中的指针变量一样(尽管最终的内存访问将是不同,"
我对此很困惑:既然a已经衰减到指针,那为什么他的意思是"内存访问会有所不同?"
这是我的代码:
// array.cpp
#include <cstdio>
using namespace std;
int main()
{
char a[6] = "hello";
char *p = "world";
printf("%c\n", a[3]);
printf("%c\n", p[3]);
}
Run Code Online (Sandbox Code Playgroud)
这是我使用g ++ -S array.cpp获得的汇编代码的一部分
.file "array.cpp"
.section .rodata
.LC0:
.string "world"
.LC1:
.string "%c\n"
.text
.globl main
.type main, @function
main:
.LFB2:
leal 4(%esp), %ecx
.LCFI0:
andl $-16, %esp
pushl -4(%ecx)
.LCFI1:
pushl %ebp
.LCFI2:
movl %esp, %ebp
.LCFI3:
pushl %ecx
.LCFI4:
subl $36, %esp
.LCFI5:
movl $1819043176, -14(%ebp)
movw $111, -10(%ebp)
movl $.LC0, -8(%ebp)
movzbl -11(%ebp), %eax
movsbl %al,%eax
movl %eax, 4(%esp)
movl $.LC1, (%esp)
call printf
movl -8(%ebp), %eax
addl $3, %eax
movzbl (%eax), %eax
movsbl %al,%eax
movl %eax, 4(%esp)
movl $.LC1, (%esp)
call printf
movl $0, %eax
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
Run Code Online (Sandbox Code Playgroud)
我无法从上面的代码中找出[3]和p [3]的机制.如:
并且,请注意以下3行代码:
movl $ 1819043176,-14(%ebp)
movw $ 111,-10(%ebp)
movl $ .LC0,-8(%ebp)
最后一个使用"movl",但为什么不覆盖-10(%ebp)的内容?(我现在知道anser :),地址是增量的,"movl $ .LC0 -8(%ebp)只会覆盖{-8,-7,-6,-5}(%ebp))
对不起,我对这个机制以及汇编代码感到很困惑......
非常感谢您的帮助.
a
是指向字符数组的指针. p
是一个指向char的指针,在这种情况下恰好是指向字符串文字.
movl $1819043176, -14(%ebp)
movw $111, -10(%ebp)
Run Code Online (Sandbox Code Playgroud)
初始化堆栈上的本地"hello"(这就是引用它的原因ebp
).由于"hello"中有超过4个字节,因此需要两个指令.
movzbl -11(%ebp), %eax
movsbl %al,%eax
Run Code Online (Sandbox Code Playgroud)
参考文献a[3]
:两步过程是因为在访问内存方面存在限制ebp
(我的x86-fu有点生疏).
movl -8(%ebp), %eax
确实引用了p
指针.
LC0
引用"相对内存"位置:一旦程序加载到内存中,就会分配一个固定的内存位置.
movsbl %al,%eax
意思是:"移动单字节,降低"(给予或采取......我必须查找它......我在这方面有点生疏).al
表示寄存器中的一个字节eax
.