Может ли размер указателей варьироваться между данными и указателями функций?
Я просто читал раздел C FAQ по указателям.
В нем обсуждается невозможность использования указателей void *
для удержания указателей функций, поскольку указатели на данные и указатели на функции могут иметь разные размеры на некоторых платформах, а void *
гарантированно будет достаточно большим, чтобы удерживать указатели на данные.
Может ли кто-нибудь привести пример платформы, где указатели на данные и указатели на функции имеют разные размеры?
Ответы
Ответ 1
> type ppp.c
#include <stdio.h>
#include <stdlib.h>
int global = 0;
int main(void) {
int local = 0;
static int staticint = 0;
int *mall;
int (*fx)(void);
fx = main;
mall = malloc(42); /* assume it worked */
printf("#sizeof pointer to local: %d\n", (int)sizeof &local);
printf("#sizeof pointer to static: %d\n", (int)sizeof &staticint);
printf("#sizeof pointer to malloc'd: %d\n", (int)sizeof mall);
printf("#sizeof pointer to global: %d\n", (int)sizeof &global);
printf("#sizeof pointer to main(): %d\n", (int)sizeof fx);
free(mall);
return 0;
}
> tcc -mc ppp.c
Turbo C Version 2.01 ...
warnings about unused variables elided ...
Turbo Link Version 2.0 ...
> ppp
#sizeof pointer to local: 4
#sizeof pointer to static: 4
#sizeof pointer to malloc'd: 4
#sizeof pointer to global: 4
#sizeof pointer to main(): 2
> tcc -mm ppp.c
> ppp
#sizeof pointer to local: 2
#sizeof pointer to static: 2
#sizeof pointer to malloc'd: 2
#sizeof pointer to global: 2
#sizeof pointer to main(): 4
tcc -mc
генерирует код в "компактной" модели; tcc -mm
генерирует код в модели "средний"
Ответ 2
В реальном режиме x86 доступ к коду и данным осуществляется с помощью сегмента + смещения, каждый из которых имеет 16-разрядное количество. Указатели "Near" были только 16-битными и использовали текущий сегмент, указатели "Far" были 32-битными и определяли сегмент и смещение. Для компиляторов C было несколько различных моделей памяти, которые вы могли бы выбрать, с разными значениями по умолчанию для указателей ближнего или дальнего порядка для кода и данных.
Например, модель памяти "Средняя" используется по умолчанию для указателей для данных, но по умолчанию указатели на код по умолчанию.
Я бы не удивился, если некоторые современные встроенные процессоры имеют похожие модели памяти.
Ответ 3
Обратите внимание, что POSIX требует, чтобы указатели на объекты и указатели на функции были одного размера:
2.12.3 Типы указателей
Все типы указателей функций должны иметь то же представление, что и указатель типа на void. Преобразование указателя функции в void * не должно изменять представление. Значение void *, возникающее в результате такого преобразования, может быть преобразовано обратно в исходный тип указателя функции с использованием явного приведения без потери информации.
Примечание: Стандарт ISO C не требует этого, но он необходим для соответствия POSIX.
Следовательно, системы, требующие соответствия POSIX, будут одинаковыми. Если вы ориентируетесь только на такие машины, вам не нужно беспокоиться о различиях.
Ответ 4
16-разрядные микроконтроллеры PIC (Microchip PIC24 и dsPIC) являются примерами устройств архитектуры Гарварда с различными размерами указателя и кода пространства. Отдельные адресные пространства различаются по размеру - на чипе SRAM имеется больший размер области чипа, чем у флэш-памяти, там гораздо меньше, поэтому указатели данных могут быть меньше.
Это также относится к архитектурам PIC12, PIC16 и PIC18, но dsPIC - это то, что я сейчас использую.
Ответ 5
Машины, которые используют Harvard Architecture, имеют отдельное хранилище для инструкций и данных и соответственно имеют отдельные адресные пространства для инструкций и данных. В такой архитектуре нет реальной причины, чтобы два адресных пространства (или их физическая память) были одинакового размера.
Ответ 6
Это зависит от ситуации. В С++ я помню, что указатели на функции-члены на самом деле являются двумя указателями в размере, но это может быть чисто детальность реализации.
В некоторых из действительно старых систем до ПК вы также можете иметь размер указателя в зависимости от того, на что ссылались (но тогда вы также можете иметь 11 бит символов: D)