Пытаетесь понять, что на самом деле представляет собой указатель на функцию? Это адрес в сегменте кода, где находится функция?

Например: этот фрагмент кода:

#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;
}

... печатает это:

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

Я думаю, я немного смущен тем, как именно стек / куча процесса соотносятся с сегментом данных / кодом ELF. Любые полезные указатели будут действительно приветствоваться. Кроме того, мой первый вопрос, так что будьте осторожны, я действительно пытаюсь научиться. Спасибо!

7
helpmelearn 14 Окт 2010 в 09:22

3 ответа

Лучший ответ

Это адрес точки входа функции - начало ее кода. Переменная a находится в стеке, поэтому неудивительно, что ее адрес значительно отличается - стеку и коду назначаются разные области кода, которые могут быть довольно далеко друг от друга.

5
sharptooth 14 Окт 2010 в 09:25
Итак, выходные данные здесь представляют собой место, где эта конкретная функция была загружена как часть сегмента кода? Есть ли способ для программы C напечатать сегмент данных, начальные / конечные адреса сегментов кода?
 – 
helpmelearn
14 Окт 2010 в 09:37
@helpmelearn: Да, это адрес, по которому находится начало функции. Я не знаю решения для поиска адресов сегментов и полагаю, что это будет зависеть от реализации. Возможно, есть какая-нибудь служебная программа, которая может сделать это для любого процесса.
 – 
sharptooth
14 Окт 2010 в 09:42

Это изображение из книги UNIX: Системное программирование должно прояснить ситуацию. .

Внизу диаграммы у вас есть текст вашей программы (младшие адреса). Как можно проверить из вашей программы. Вот где будет находиться foo ().

alt text

3
Srikar Appalaraju 14 Окт 2010 в 09:36

Следует иметь в виду, что ваш код не полностью соответствует стандартам. Если вы используете gcc -Wall -Wextra -pedantic -ansi, вы получите жалобу на строку, в которой вы печатаете указатель на функцию. Это связано с тем, что стандарт не гарантирует, что указатели функций могут быть преобразованы в указатели void. C разработан для работы на многих различных архитектурах, и если архитектура является архитектурой Гарварда (отдельная память для инструкций и данных), могут быть веские причины для того, чтобы сделать эти указатели разных размеров.

Я предполагаю, что на практике это вряд ли имеет значение, но хороший факт, о котором следует знать. Особенно, когда вы пытаетесь узнать интимные подробности C.

2
kasterma 28 Окт 2010 в 02:44