Например: sizeof(char*)
возвращает 4. Как и int*
, long long*
, все, что я пробовал. Есть ли исключения из этого?
Всегда ли sizeof (некоторый указатель) равен четырем?
Ответы (17)
Гарантия, которую вы получите, - это sizeof(char) == 1
. Нет никаких других гарантий, в том числе гарантии, что sizeof(int *) == sizeof(double *)
.
На практике указатели будут иметь размер 2 в 16-битной системе (если вы можете его найти), 4 в 32-битной системе и 8 в 64-битной системе, но полагаться на данную размер.
sizeof(int) <= sizeof(long)
. Они могут быть такими же или long
могут быть значительно больше, чем int
, но меньше никогда не будет.
- person Jon Hanna; 10.08.2012
sizeof(char*) == sizeof(void*)
?
- person Destructor; 04.04.2016
int, FP, Struct, char
- это особенность прошлого - сейчас я не знаю никаких вариаций. OTOH, указатели на функции и указатели на объекты различаются.
- person chux - Reinstate Monica; 24.03.2020
sizeof int* != sizeof double*
? Означает ли это, что int
или double
, находящиеся в куче, не могут иметь адреса большего размера? Например, если sizeof int*
равно 4, а sizeof double*
равно 8, то двойные числа могут иметь большие 8-байтовые адреса в куче, в то время как целые числа ограничиваются только 4-байтовыми адресами в куче? А как насчет пользовательских типов? Возможно ли также, что sizeof class1*
! = sizeof class2*
?
- person Herrgott; 06.05.2021
Даже на простой 32-битной платформе x86 вы можете получить указатели разных размеров, попробуйте это для примера:
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
В Visual C ++ 2008 я получаю 4, 12 и 8 для размеров указателей на функцию-член.
Рэймонд Чен рассказал об этом здесь.
char
‹short
?
- person user3207158; 11.11.2019
char
всегда меньше или равно short
, ..., int
всегда меньше или равно long
и т. Д. У меня нет стандарта под рукой, поэтому я не могу назвать эталонный банкомат.
- person Cole Johnson; 12.11.2019
Еще одно исключение из уже опубликованного списка. На 32-битных платформах указатели могут занимать 6, не 4 байта:
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Если вы скомпилируете эту программу с Open Watcom и запустите ее, вы получите 6, потому что дальние указатели, которые она поддерживает, состоят из 32-битного смещения и 16-битных значений сегмента.
если вы компилируете для 64-битной машины, то это может быть 8.
sizeof(char*)==1
? Уверены ли вы? Вы не имеете в виду size(char)==1
?
- person Aaron McDaid; 02.11.2013
Технически говоря, стандарт C гарантирует только то, что sizeof (char) == 1, а остальное зависит от реализации. Но на современных архитектурах x86 (например, чипах Intel / AMD) это довольно предсказуемо.
Вы, наверное, слышали, что процессоры описываются как 16-битные, 32-битные, 64-битные и т. Д. Это обычно означает, что процессор использует N-биты для целых чисел. Поскольку указатели хранят адреса памяти, а адреса памяти являются целыми числами, это фактически говорит вам, сколько битов будет использоваться для указателей. sizeof обычно измеряется в байтах, поэтому код, скомпилированный для 32-битных процессоров, сообщит, что размер указателей будет равен 4 (32 бит / 8 бит на байт), а код для 64-битных процессоров сообщит, что размер указателей равен 8 (64 бит / 8 бит на байт). Отсюда и ограничение в 4 ГБ ОЗУ для 32-битных процессоров - если каждый адрес памяти соответствует байту, для адресации большего объема памяти вам нужны целые числа больше 32 бит.
Размер указателя в основном зависит от архитектуры системы, в которой он реализован. Например, размер указателя в 32-битном режиме составляет 4 байта (32-битный) и 8 байтов (64-битный) на 64-битных машинах. Типы битов в машине - это не что иное, как адрес памяти, который она может иметь. 32-битные машины могут иметь 2^32
адресное пространство, а 64-битные машины могут иметь до 2^64
адресных пространств. Таким образом, указатель (переменная, указывающая на ячейку памяти) должен иметь возможность указывать на любой адрес памяти (2^32 for 32 bit and 2^64 for 64 bit
), который хранится в машине.
По этой причине мы видим, что размер указателя составляет 4 байта на 32-битной машине и 8 байтов на 64-битной машине.
В дополнение к различиям в 16/32/64 бит могут происходить даже более странные вещи.
Были машины, на которых sizeof (int *) будет иметь одно значение, вероятно, 4, но где sizeof (char *) больше. Машины, которые естественным образом обращаются к словам, а не к байтам, должны «увеличивать» указатели на символы, чтобы указать, какую часть слова вы действительно хотите, чтобы правильно реализовать стандарт C / C ++.
Сейчас это очень необычно, поскольку разработчики оборудования узнали значение байтовой адресации.
void*
и char*
обрабатываются программно и дополняются 3-битным смещением внутри слова, но поскольку на самом деле нет 64-битного адресного пространства, смещение сохраняется в 3-х старших битах 64 -битное слово. Таким образом, char*
и int*
имеют одинаковый размер, но имеют разные внутренние представления - и код, предполагающий, что указатели на самом деле являются просто целыми числами, может сильно потерпеть неудачу.
- person Keith Thompson; 01.07.2012
8-битные и 16-битные указатели используются в большинстве низкопрофильных микроконтроллеров. Это означает каждую стиральную машину, микро, холодильник, старые телевизоры и даже автомобили.
Можно сказать, что это не имеет ничего общего с программированием в реальном мире. Но вот один из реальных примеров: Arduino с оперативной памятью 1-2-4k (в зависимости от чипа) с 2-х байтовыми указателями.
Он недавний, дешевый, доступный для всех и заслуживающий программирования.
В дополнение к тому, что люди говорят о 64-битных (или любых других) системах, существуют другие виды указателей, кроме указателей на объект.
Указатель на член может иметь почти любой размер, в зависимости от того, как они реализованы вашим компилятором: они даже не обязательно должны быть одинакового размера. Попробуйте использовать указатель на член класса POD, а затем указатель на член, унаследованный от одного из базовых классов класса с несколькими базами. Как весело.
Насколько я помню, он основан на размере адреса памяти. Таким образом, в системе с 32-битной схемой адреса sizeof вернет 4, поскольку это 4 байта.
sizeof (unsigned int) == sizeof (signed int)
это требование содержится в 3.9.1 / 3. Для каждого из стандартных целочисленных типов со знаком существует соответствующий (но другой) стандартный целочисленный тип без знака: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
и unsigned long long int
, каждый из которых занимает одинаковый объем памяти и имеет одинаковое выравнивание. требования как соответствующий целочисленный тип со знаком
- person Ben Voigt; 31.08.2013
В общем, sizeof (почти все) изменится при компиляции на разных платформах. На 32-битной платформе указатели всегда имеют одинаковый размер. На других платформах (очевидным примером является 64-битная версия) это может измениться.
Нет, размер указателя может варьироваться в зависимости от архитектуры. Есть множество исключений.
Размер указателя и int составляет 2 байта в компиляторе Turbo C на 32-битной машине Windows.
Таким образом, размер указателя зависит от компилятора. Но обычно большинство компиляторов реализовано для поддержки 4-байтовой переменной-указателя в 32-битной и 8-байтовой переменной-указателя на 64-битной машине).
Таким образом, размер указателя не одинаков на всех машинах.
В Win64 (Cygwin GCC 5.4) рассмотрим следующий пример:
Сначала протестируйте следующую структуру:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Код теста ниже:
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
Результат ниже:
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
Вы можете видеть, что в 64-битной версии sizeof(pointer)
равно 8
.
Причина, по которой размер вашего указателя составляет 4 байта, заключается в том, что вы компилируете для 32-битной архитектуры. Как указал FryGuy, на 64-битной архитектуре вы увидите 8.
Указатель - это просто контейнер для адреса. На 32-битной машине ваш диапазон адресов составляет 32 бита, поэтому указатель всегда будет 4 байта. На 64-битной машине с диапазоном адресов 64 бита указатель будет иметь размер 8 байт.
Просто для полноты и исторического интереса в мире 64-битных платформ существовали различные соглашения о размерах длинных и длинных длинных типов, называемых LLP64 и LP64, в основном между системами типа Unix и Windows. Старый стандарт под названием ILP64 также сделал int = 64-битным.
Microsoft сохранила LLP64, где longlong = 64-битная ширина, но долгое время оставалась равной 32 для облегчения портирования.
Type ILP64 LP64 LLP64
char 8 8 8
short 16 16 16
int 64 32 32
long 64 64 32
long long 64 64 64
pointer 64 64 64
Источник: https://stackoverflow.com/a/384672/48026