Действительно ли этот фрагмент кода четко определен в ANSI C? В моей системе (Linux x86_64) это, кажется, работает очень хорошо и печатает адрес, но это будет всегда иметь место? Например, параметр мог бы быть передан через регистр, и взятие адреса этого не кажется правильным.
#include <stdio.h>
void foo(int a)
{
printf("%p\n", &a);
}
int main(void)
{
foo(42);
return 0;
}
Править: Похож на GCC, поместит значение, которое передается регистром в стек прежде, чем взять адрес ее.
<foo>:
55 push rbp
48 89 e5 mov rbp,rsp
48 83 ec 10 sub rsp,0x10
89 7d fc mov DWORD PTR [rbp-0x4],edi
b8 1c 06 40 00 mov eax,0x40061c
48 8d 55 fc lea rdx,[rbp-0x4]
48 89 d6 mov rsi,rdx
48 89 c7 mov rdi,rax
b8 00 00 00 00 mov eax,0x0
e8 d8 fe ff ff call 4003c0 <printf@plt>
c9 leave
c3 ret
Да, это совершенно законно - конечно, вы не вернете этот адрес из функции, потому что к моменту возврата foo
это бессмысленно.
Для адресации вашего путаница: Да, аргумент может быть передан регистром, но когда он становится локальной переменной в вызываемой функции, он такой же, как и любая другая локальная переменная. Если этот адрес берется и используется, компилятор должны гарантировать, что у него есть реальный адрес, по которому к нему можно получить доступ, создав реальную переменную стека. В противном случае компилятор может оптимизировать, чтобы сохранить ее в регистре, даже не создавая ее в памяти.
Это совершенно законно. Но вам нужно подумать о масштабах и сроке жизни того, что вы получили адрес.
Если вы попытаетесь передать его обратно из функции, этот адрес может больше не указывать на действительные данные. Как и в большинстве C, это дает вам возможность выстрелить себе в ногу.