2010-10-14 1 views
7

Cố gắng hiểu những gì con trỏ thực hiện chức năng thực sự đại diện? Đó có phải là địa chỉ trong phân đoạn mã nơi chức năng cư trú không?Giá trị con trỏ của con trỏ hàm đại diện cho cái gì?

Đối với ví dụ: đoạn mã này:

#include <stdio.h> 

void foo(void) 
{ 
} 

int main(void) 
{ 
    int a = 10; 
    printf("a's address: %p\n", &a); 
    printf("foo's address: %p\n", foo); 
    return 0; 
} 

... in này:

[sh/prog-exercises/adam]:./a.out 
a's address: 0xbfffb414 
foo's address: 0x8048430 

Tôi đoán Tôi là một chút nhầm lẫn với cách chính xác chồng/đống của một quá trình liên quan với phân đoạn dữ liệu ELF/phân đoạn mã. Bất kỳ con trỏ hữu ích nào cũng sẽ thực sự được chào đón. Ngoài ra, câu hỏi đầu tiên của tôi, vì vậy hãy nhẹ nhàng, tôi thực sự đang cố gắng học hỏi. Cảm ơn!

Trả lời

5

Đó là địa chỉ của điểm nhập chức năng - bắt đầu mã của nó. Biến số a được đặt trên ngăn xếp, vì vậy không có gì ngạc nhiên khi địa chỉ của nó khác nhau đáng kể - ngăn xếp và mã được chỉ định các vùng mã khác nhau có thể khá xa nhau.

+0

Phải, vì vậy, đầu ra ở đây đại diện cho vị trí mà hàm cụ thể này đã được tải như một phần của đoạn mã? Có cách nào để chương trình C in đoạn dữ liệu, phân đoạn mã bắt đầu/kết thúc địa chỉ không? – helpmelearn

+0

@helpmelearn: Có, đó là địa chỉ bắt đầu chức năng. Tôi không biết một giải pháp cho việc tìm kiếm các địa chỉ phân đoạn và tôi cho rằng nó sẽ phụ thuộc vào việc triển khai thực hiện. Có lẽ có một số chương trình tiện ích có thể làm điều này cho bất kỳ quá trình nào. – sharptooth

3

Hình ảnh này từ sách UNIX: Systems Programming sẽ làm rõ mọi thứ.

Ở cuối biểu đồ, bạn có văn bản chương trình của mình (địa chỉ thấp). Như có thể được xác nhận từ chương trình của bạn. Đó là nơi foo() sẽ cư trú.

alt text

2

Một điều cần lưu ý là mã của bạn là không hoàn toàn tiêu chuẩn phù hợp. Nếu bạn sử dụng gcc -Wall -Wextra -pedantic -ansi, bạn sẽ nhận được đơn khiếu nại về dòng nơi bạn đang in con trỏ hàm. Điều này là do tiêu chuẩn không đảm bảo rằng các con trỏ hàm có thể được chuyển đổi thành con trỏ void. C được thiết kế để làm việc trên nhiều kiến ​​trúc khác nhau, và nếu kiến ​​trúc là một kiến ​​trúc Harvard (chỉ dẫn riêng biệt và bộ nhớ dữ liệu) có thể có lý do chính đáng để làm cho các con trỏ có kích thước khác nhau.

Tôi đoán rằng trong thực tế nó không có khả năng quan trọng, nhưng một factoid tốt để được nhận thức. Esp khi bạn đang cố gắng tìm hiểu chi tiết thân mật của C.