Мне сказали c-faq, что компилятор делает разные вещи для работы с [i], а a - это массив или указатель, Вот пример из c-faq:
char a[] = "hello"; char *p = "world";
Учитывая вышеприведенные объявления, когда компилятор видит выражение a [3], он испускает код для начала в местоположении `` a '', перемещает три мимо него и выбирает там символ. Когда он видит выражение p [3], он испускает код для начала в месте "p", извлекает значение указателя там, добавляет три к указателю и, наконец, извлекает символ, на который указывает.
Но мне сказали, что при работе с [i] компилятор стремится преобразовать (который является массивом) в указатель на массив. Поэтому я хочу видеть коды сборки, чтобы узнать, что правильно.
EDIT:
Здесь источник этого утверждения. 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
Я не могу понять механизм [3] и p [3] из приведенных выше кодов. Например:
- где был "привет" инициализирован?
- Что означает $1819043176? возможно, это адрес памяти "привет" (адрес a)?
- Я уверен, что "-11 (% ebp)" означает [3], но почему?
- В "movl -8 (% ebp),% eax", содержимое poniter p сохраняется в EAX, правильно? Таким образом, $.LC0 означает содержимое указателя p?
- Что означает "movsbl% al,% eax"?
-
И, обратите внимание на эти 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))
Извините, но я полностью смущен этим механизмом, а также код сборки...
Большое спасибо за вашу помощь.