2010-07-11 33 views
9

Đoạn mã này có được xác định rõ trong ANSI C không? Trên hệ thống của tôi (Linux x86_64) có vẻ như chỉ chạy tốt và in một địa chỉ, nhưng nó sẽ luôn luôn như vậy? Ví dụ. tham số có thể được chuyển qua một thanh ghi, và lấy địa chỉ của nó có vẻ không đúng.Có hợp pháp để lấy địa chỉ của tham số chức năng không?

#include <stdio.h> 

void foo(int a) 
{ 
    printf("%p\n", &a); 
} 

int main(void) 
{ 
    foo(42); 
    return 0; 
} 

EDIT: Dường như GCC sẽ đặt giá trị được chuyển bằng cách đăng ký vào ngăn xếp trước khi lấy địa chỉ của nó.

<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 <[email protected]> 
    c9      leave 
    c3      ret 

Trả lời

8

Có, điều này hoàn toàn hợp pháp - tất nhiên bạn sẽ không trả lại địa chỉ đó từ hàm, vì thời gian foo trả về, điều đó là vô nghĩa.

1

Hoàn toàn hợp pháp. Nhưng bạn cần phải suy nghĩ về phạm vi và tuổi thọ của những gì bạn đã nhận được địa chỉ của.

Nếu bạn cố gắng chuyển nó ra khỏi hàm, địa chỉ đó có thể không trỏ đến dữ liệu hợp lệ nữa. Như trong phần lớn của C, điều này mang lại cho bạn khả năng để bắn mình vào chân.

16

Để giải quyết sự nhầm lẫn của bạn: Có, đối số có thể là đã vượt qua bằng thanh ghi, nhưng khi nó trở thành biến cục bộ trong hàm được gọi, nó giống như bất kỳ biến cục bộ nào khác. Nếu địa chỉ của nó được lấy và sử dụng, trình biên dịch sẽ phải đảm bảo nó có một địa chỉ thực mà qua đó nó có thể được truy cập bằng cách tạo ra một biến stack thực. Nếu không, trình biên dịch có thể tối ưu hóa để giữ nó trong sổ đăng ký mà không bao giờ khởi tạo nó trong bộ nhớ.

+2

+1, câu trả lời của bạn hoàn chỉnh hơn :) – Stephen

Các vấn đề liên quan