Что гарантировано относительно размера указателя функции? - PullRequest
29 голосов
/ 15 октября 2010

В C мне нужно знать размер структуры, в которой есть указатели на функции. Можно ли гарантировать, что на всех платформах и архитектурах:

  • размер пустоты * равен размеру указателя функции?
  • размер указателя функции не отличается в зависимости от типа возвращаемого значения?
  • размер указателя функции не отличается из-за типов его параметров?

Я предполагаю, что ответ на все вопросы положительный, но я хочу быть уверенным. Для контекста я звоню sizeof(struct mystruct) и больше ничего.

Ответы [ 4 ]

31 голосов
/ 15 октября 2010

Из спецификации C99, раздел 6.2.5, параграф 27:

Указатель на void должен иметь те же требования к представлению и выравниванию, что и указатель на тип символа.Аналогично, указатели на квалифицированные или неквалифицированные версии совместимых типов должны иметь одинаковые требования к представлению и выравниванию.Все указатели на типы конструкций должны иметь те же требования к представлению и выравниванию, что и другие.Все указатели на типы объединения должны иметь те же требования к представлению и выравниванию, что и другие.Указатели на другие типы не обязательно должны иметь одинаковые требования к представлению или выравниванию.

Так что нет;нет никакой гарантии, что void * может содержать указатель на функцию.

И раздел 6.3.2.3, пункт 8:

Указатель на функцию одного типа может быть преобразован вуказатель на функцию другого типа и обратно;результат должен сравниваться равным исходному указателю.

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

14 голосов
/ 15 октября 2010

Нет, нет, нет.

C не поддерживает гарвардские архитектуры с разными размерами кода и указателей данных, потому что в идеале при программировании для такой архитектуры вы хотите хранить данные в памяти программы (строковые литералы и т. П.) И делать это вам указатели объектов в пространство кода. Но это не запрещает их, так как в стандарте указатели функций могут ссылаться на адресное пространство, размер которого отличается от адресного пространства данных.

Однако любой указатель на функцию может быть приведен к другому типу указателя на функцию [*] и обратно без изменения значения, так же, как любой указатель объекта может быть приведен к void* и обратно. Поэтому было бы довольно удивительно, если указатели на функции изменяются в размерах в соответствии с их сигнатурой. Нет очевидного «использования» для дополнительного пространства, если вам нужно каким-то образом сохранить то же значение в меньшем пространстве, а затем извлечь его при отбрасывании.

[*] Спасибо, шот.

8 голосов
/ 15 октября 2010

В дополнение к другим ответам Википедия говорит следующее:

http://en.wikipedia.org/wiki/Function_pointer

Хотя указатели на функции в C и C ++ могут быть реализованы как простые адреса, так что обычно sizeof(Fx)==sizeof(void *), указатели-члены в C ++ часто реализуются как «толстые указатели», обычно в два-три раза превышающие размер простого указателя функции, чтобы иметь дело с виртуальным наследованием.

Указатель функцииабстракция.Пока требования стандарта выполнены, все возможно.То есть, если в вашей программе менее 256 функций, указатели на функции могут быть реализованы с использованием одного байта со значением 0 для NULL и значениями от 1 до 255 в качестве индекса в таблице с физическими адресами.Если вы превысили 255 функций, его можно расширить на 2 байта.

2 голосов
/ 04 сентября 2014

Существует практический пример разных размеров, которые раньше были общими. В MS-DOS и раннем программировании на Windows C в «средней» модели памяти у вас были 16-битные указатели данных, но 32-битные функциональные указатели, а «компактная» модель памяти была наоборот.

...