Результат sizeof для массивов и указателей C++
В архитектуре x86_64 размер указателя составляет 8 байтов. Для меня имеет смысл, чтоsizeof(x)
должен вернуть 8. Я понимаю, что char
это один байт, а 5 байтов - это размер массива z
. Какая интуиция стоит за тем, почемуsizeof(z)
не возвращает 8?
int* x = new int[10];
char z[5];
// Returns 8
std::cout << "This is the size of x: " << sizeof(x) << std::endl;
// Returns 5
std::cout << "This is the size of z: " << sizeof(z) << std::endl;
5 ответов
Какая интуиция стоит за тем, почему
sizeof(z)
не возвращает 8?
z
не указатель. Следовательноsizeof(z)
это не что иное, а 5 байт. В случаеsizeof
, массив не распадается на указатель. Обратитесь: Что такое распад массива?
В C++ есть несколько неявных преобразований, таких как массив в указатель, перечисление в целое число, double
к float
, производный от базы, любой указатель на void*
и так далее. Что может заставить нас задуматься, такие же ли их размеры или что?
Следовательно, лакмусовая бумажка для самопонимания - создать ссылку на указатель и попытаться назначить другой тип. Это приводит к ошибке для несовпадающих типов. например
int *x = new int[5], *&px = x; // OK
int z[5], *&pz = z; // error: can't initialize
Вы определили x
как указатель на char, поэтому sizeof(x)
дает размер указателя на char. В текущей реализации это обычно 32 или 64 бита. Аchar
обычно составляет 8 бит, поэтому вы можете ожидать sizeof(char *)
чтобы получить 4 или 8 на большинстве современных компиляторов.
Вы определили z
как массив из 5 символов, поэтому sizeof(z)
дает размер массива из 5 символов. Поскольку элементы массива смежны, иsizeof(char)
гарантированно равняется 1, очевидным значением для него будет 5.
Если (например) вы помещаете в структуру массив из 5 символов, за которым следует (скажем) int
, очень велика вероятность, что компилятор вставит некоторый отступ между этими двумя элементами.
Каждый символ имеет размер "1" Предположим, когда вы его скомпилируете
//It returns 1
char z='a';
std::cout << "This is the size of z: " << sizeof(z) << std::endl;
//It returns 5 because it is an array of 5 characters
char z[5];
std::cout << "This is the size of z: " << sizeof(z) << std::endl;
Когда вы передаете имя массива в sizeof, вы хотите знать, сколько "байтов" данных принадлежит этому массиву.
Когда вы передаете указатель на sizeof, вы хотите знать, сколько "байтов" занимает этот указатель.
Разница очень очевидна, когда вы передаете имя массива в качестве аргумента функции. В этом случае функция не может видеть всю область данных, которую занимает массив. Он видит только тип "указатель".
Размер указателя зависит от многих факторов, включая архитектуру процессора, компилятор, операционную систему и т. Д.
Таким образом, для 32 - разрядного компьютера, размер указателя может быть 4 байта, а 64 - разрядные компьютеры могут иметь 8 байтов (Ключевое слово: "может"). Или, 64-битный компьютер с 32-битной ОС будет иметь 4 байта. Тем не менее, в определенной архитектуре все типы указателей (void*, int*, char*, long* и т. Д.) Будут иметь одинаковый размер (кроме указателей на функции).
То есть указатели в C (или C++) не имеют фиксированного размера.