Все ли указатели данных имеют одинаковый размер на одной платформе для всех типов данных? - PullRequest
44 голосов
/ 07 августа 2009

Являются ли char*, int*, long* или даже long long* одинакового размера (на данной платформе)?

Ответы [ 8 ]

49 голосов
/ 07 августа 2009

Не гарантируется, что они будут одинакового размера, хотя на платформах, с которыми у меня есть опыт, они обычно есть.

C 2011 онлайн-проект :

6.2.5 Типы
...
28 Указатель на void должен иметь те же требования к представлению и выравниванию, что и указатель на тип символа. 48) Аналогично, указатели на квалифицированные или неквалифицированные версии совместимые типы должны иметь одинаковые требования к представлению и выравниванию. Все указатели на типы конструкций должны иметь одинаковые требования к представлению и выравниванию как друг друга. Все указатели на типы объединения должны иметь одинаковое представление и требования выравнивания как друг друга. Указатели на другие типы не обязательно должны иметь одинаковые требования представления или выравнивания.
48) Те же требования к представлению и выравниванию подразумевают взаимозаменяемость, как аргументы функций, возвращаемые значения из функций и членов объединений.
18 голосов
/ 07 августа 2009

Не обязательно. Стандарт не гарантирует sizeof(double*) == sizeof(int*). Например, предположим, что процессор с двумя адресными шинами разной ширины (как на некоторых процессорах архитектуры Гарварда) может иметь указатели разных размеров.

7 голосов
/ 07 августа 2009

Обратите внимание на то, что говорится в стандарте C - как цитирует Джон Боде. Также обратите внимание, что стандарт C вообще ничего не говорит о размерах указателей на функции.

Стандарт POSIX устанавливает некоторые дополнительные требования:

2.12.3 Типы указателей

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

Примечание: стандарт ISO C не требует этого, но это требуется для соответствия POSIX.

7 голосов
/ 07 августа 2009

На 16-разрядных встраиваемых процессорах, в которых имеется (страничная) ОЗУ и / или флэш-память, использование страниц может привести к тому, что указатели будут иметь разные размеры, хотя это не зависит от размера данных, на которые они указывают.

Например, на процессоре Freescale HCS12 с флэш-памятью все указатели данных имеют 16 бит.

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

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

Вполне возможно, что 16-разрядный процессор с ОЗУ с накоплением памяти также будет иметь разные размеры для ближних и дальних указателей данных.

4 голосов
/ 07 августа 2009

При программировании реального режима x86 с помощью Watcom C у вас может быть смешанная модель памяти, использующая 16-разрядные ближние указатели и 32-разрядные дальние указатели.

4 голосов
/ 07 августа 2009

Нет такой гарантии ни в стандартах ISO C, ни в C ++, но на практике мне еще предстоит увидеть платформу, на которой это не выполняется.

Обратите внимание, что независимо от этого, reinterpret_cast указание одного указателя на другой чаще всего приведет к U.B., с некоторыми исключениями (void* и unsigned char* для POD). Как и любые профсоюзные трюки. Итак, очевидный вопрос: зачем тебе это?

2 голосов
/ 07 августа 2009

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

0 голосов
/ 07 августа 2009

Обычно да, все указатели на что-либо, независимо от того, указывают ли они на int, long или на строку, массив строк или функцию, указывают на один адрес памяти, который имеет одинаковый размер на машине. Это связано с тем, что Processer на машине имеет регистр адресов, в который загружаются эти указатели, а размер этого регистра адресов управляет размером указателей.

Единственное исключение может иметь место, например, на старых 16-разрядных компьютерах Intel 8088, где для определения адреса памяти использовался двухэтапный процесс, включающий 16-разрядный указатель сегмента (который идентифицировал блок памяти размером 64 КБ в адресе 1 МБ). пробел), а затем второй 16-битный адрес памяти, чтобы определить конкретный адрес памяти в этом сегменте. Эти два 16-битных адреса были затем объединены, чтобы получить полный 20-битный адрес памяти. В таком случае, я полагаю, можно было бы различить отдельные 16-битные адреса и комбинированный 20-битный адрес.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...