Все ли указатели данных имеют одинаковый размер на одной платформе для всех типов данных?
Являются char*
, int*
, long*
или даже long long*
одного размера (на данной платформе)?
8 ответов
Они не гарантируют одинаковый размер, хотя на платформах, с которыми я обычно сталкиваюсь, они есть.
C 2011 онлайн проект:
6.2.5 Типы
...
28 Указатель наvoid
должны иметь те же требования к представлению и выравниванию, что и указатель на тип символа. 48) Аналогично, указатели на квалифицированные или неквалифицированные версии совместимых типов должны иметь одинаковые требования к представлению и выравниванию. Все указатели на типы конструкций должны иметь те же требования к представлению и выравниванию, что и другие. Все указатели на типы объединений должны иметь те же требования к представлению и выравниванию, что и другие. Указатели на другие типы не обязательно должны иметь одинаковые требования к представлению или выравниванию.
48) Те же требования к представлению и выравниванию подразумевают взаимозаменяемость в качестве аргументов функций, возвращаемых значений из функций и членов объединений.
Не обязательно. Стандарт не гарантирует sizeof(double*) == sizeof(int*)
, Например, предположим, что процессор с двумя адресными шинами разной ширины (как на некоторых процессорах архитектуры Гарварда) может иметь указатели разных размеров.
На 16-разрядных встраиваемых процессорах, которые объединяют (выгружают) ОЗУ и / или флэш-память, использование страниц может привести к тому, что указатели будут иметь разные размеры - хотя это не зависит от размера данных, на которые они указывают.
Например, на процессоре Freescale HCS12 с флэш-памятью все указатели данных имеют 16 бит.
Однако указатели функций составляют 16 битов для ближних указателей (для кода на той же странице, что и вызывающая функция, или в небанкованной флэш-памяти), или 24 бита для дальних указателей (для кода на другой странице), включая номер страницы в адресе,
Ситуация усложняется, если вы хотите хранить постоянные данные в страничной флэш-памяти, поскольку из-за ограничения размера указателя данных функция, использующая данные, должна находиться на той же странице, что и данные, к которым осуществляется доступ.
Можно предположить, что 16-разрядный процессор с оперативной памятью в банках также будет иметь разные размеры для ближних и дальних указателей данных.
Обратите внимание на то, что говорится в стандарте C - как цитирует Джон Боде. Также обратите внимание, что стандарт C вообще ничего не говорит о размерах указателей на функции.
Стандарт POSIX устанавливает некоторые дополнительные требования:
2.12.3 Типы указателей
Все типы указателей на функции должны иметь то же представление, что и указатель типа на void. Преобразование указателя на функцию void * не должно изменять представление. Значение void *, полученное в результате такого преобразования, может быть преобразовано обратно в исходный тип указателя функции, используя явное приведение, без потери информации.
Примечание: стандарт ISO C не требует этого, но это требуется для соответствия POSIX.
При программировании реального режима x86 с помощью Watcom C вы можете использовать смешанную модель памяти, используя 16-битные ближние и 32-битные дальние указатели.
Нет такой гарантии ни в стандартах ISO C, ни в C++, но на практике мне еще предстоит увидеть платформу, на которой это не выполняется.
Обратите внимание, что независимо от этого, reinterpret_cast
Использование одного указателя на другой чаще всего приводит к UB, за некоторыми исключениями (void*
, а также unsigned char*
для PODS). Как и любые профсоюзные трюки. Таким образом, очевидный вопрос: зачем вам это?
В дни DOS защищенного режима указатель на функцию и указатель на данные могут иметь разную длину, поскольку данные могут находиться в другом разделе.
Обычно да, все указатели на что-либо, независимо от того, указывают ли они на int или long, или на строку, или на массив строк, или на функцию, указывают на один адрес памяти, который имеет одинаковый размер на машине. Это связано с тем, что Processer на компьютере имеет адресный регистр, в который загружаются эти указатели, а размер этого адресного регистра управляет размером указателей.
Единственное исключение может быть в таких случаях, как старые 16-разрядные машины Intel 8088, где для определения адреса памяти использовался двухэтапный процесс, включающий 16-разрядный указатель сегмента (который идентифицировал блок памяти размером 64 КБ в адресном пространстве 1 МБ), и затем второй 16-битный адрес памяти, чтобы идентифицировать конкретный адрес памяти в этом сегменте. Затем эти два 16-битных адреса были объединены, чтобы получить полный 20-битный адрес памяти. В таком случае, я полагаю, можно было бы различить отдельные 16-битные адреса и комбинированный 20-битный адрес.