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