Подтвердить что ты не робот

Что гарантируется относительно размера указателя функции?

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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