【发布时间】:2011-01-05 14:18:31
【问题描述】:
c-faq 告诉我,当 a 是数组或指针时,编译器会做不同的事情来处理 a[i]。以下是来自 c-faq 的示例:
char a[] = "hello"; char *p = "world";鉴于上面的声明,当编译器看到表达式 a[3] 时,它会发出代码以从位置“a”开始,移动三个过去,然后从那里获取字符。当它看到表达式 p[3] 时,它会发出代码从位置“p”开始,获取那里的指针值,将指针加 3,最后获取指向的字符。
但有人告诉我,在处理 a[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]);
}
这是我使用 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
我无法从上面的代码中弄清楚 a[3] 和 p[3] 的机制。如:
- “hello”在哪里初始化?
- 1819043176 美元是什么意思?可能是“hello”的内存地址(a的地址)?
- 我确定“-11(%ebp)”表示 a[3],但为什么呢?
- 在“movl -8(%ebp), %eax”中,指针 p 的内容存储在 EAX 中,对吗?那么 $.LC0 是指指针 p 的内容吗?
- “movsbl %al,%eax”是什么意思?
-
并且,请注意以下 3 行代码:
movl $1819043176, -14(%ebp)
movw $111, -10(%ebp)
movl $.LC0, -8(%ebp)最后一个使用“movl”,但为什么没有覆盖-10(%ebp)的内容? (我现在知道分析器了 :),地址是递增的,“movl $.LC0 -8(%ebp) 只会覆盖 {-8, -7, -6, -5}(%ebp))
对不起,我对机制以及汇编代码完全感到困惑......
非常感谢您的帮助。
【问题讨论】:
-
我认为你的这句话“编译器倾向于将一个(这是一个数组)转换为一个指向数组的指针”是不正确的。请告诉我这是谁对你说的?
-
+1,在询问之前自己尝试一下。
-
不是指向数组的指针,指向字符的指针。
-
+1 用于检查 ASM。 你已经开始了,蚱蜢...
-
@Prasoon Saurrav 我找到了我的声明的来源,发现我的和他的之间存在细微差别。它在这里:c-faq.com/aryptr/aryptrequiv.html 注意这句话:“ a[i] 形式的表达式导致数组按照上面的规则衰减为指针,然后像表达式中的指针变量一样被下标p[i] (尽管最终的内存访问会有所不同,“我对此感到很困惑:既然 a 已经衰减为指针,那么他为什么要说“内存访问会有所不同?”
标签: c++ c arrays pointers assembly