C/C++

C/C++ Как устроена память, выделенная для структуры с указателем *next?

 #include 
struct elem
{
int num; /* Номер вершины */
int suns; /* Количество сыновей */
char str[20]; /* Строка с номерами сыновей */
elem *next; /* Указатель на следующую вершину */
} *head;
int main()
{
printf("sizeof(int) = %d\n", sizeof(int));
printf("sizeof(char str[20]) = %d\n", sizeof(head->str));
printf("sizeof(elem *next) = %d\n", sizeof(head->next));
printf("sizeof(elem) = %d\n", sizeof(elem));
}
Размеры по отдельности:
int - 4b;
char str[20] - 20b;
elem *next - 8b.
Итого по отдельности 36 байт. Но общий размер структуры выдает 40 байт. Причем если закомментировать указатель "elem *next", то общий размер структуры будет соответствовать сумме размеров "int" и "char str[20]" по отдельности, т.е. 28 байт.

Собственно вопрос, откуда берутся еще 4 байта при добавлении указателя? Т.е. вместо 8 байт прибавляется 12 байт.
выравнивание
https://docs.microsoft.com/ru-ru/cpp/build/x64-software-conventions?view=msvc-170&viewFallbackFrom=vs-2015#scalar-types
elem *next; выравнивается до смещения кратного 8 байт
Дима Варакса
Дима Варакса
80 864
Лучший ответ
Александр Красильников 28 байт (без указателя) не требуют выравнивания, а указатель на 8 байт требует еще 4 байта для выравнивания? И я не знаю что значит выравнивание, я только изучаю...
Александр Красильников А не подскажете почему в Примере 4 с union получается 8 байт?
Александр Красильников А как там данные располагаются? Общий размер же больше...
Александр Красильников 3 элемента - 14 байт, но они занимают 8 байт? Я этот момент не догнал...
На архитектуре x64 структура данных выровнена кратно 8 байтам. Чтобы не терять 4 байта, добавьте их к размеру своей строки.
 #include  
struct node {
int id;
int count;
node* next;
char str[24];
} Node, *head;
int main() {
printf("sizeof(head->id) = %zu\n", sizeof(head->id));
printf("sizeof(head->count) = %zu\n", sizeof(head->count));
printf("sizeof(head->next) = %zu\n", sizeof(head->next));
printf("sizeof(head->str) = %zu\n", sizeof(head->str));
printf("sizeof(Node) = %zu\n", sizeof(Node));
}
Сергей Балашов
Сергей Балашов
71 418
Я вижу закономерность, по которой размер структуры всегда четный размеру наибольшего базового типа . Указатель 8 байт - значит размер будет четным 8. Убрать указатель - будет четный 4 (инт), убрать инты - будет четный 1 (чар).
На жестких дисках так же - размер файла всегда кратный размеру сектора. Иначе для построения таблицы данных пришлось тратилась бы наверное половину всего обьема.
И больше времени на обработку этой самой таблицы.
E.
El'dar ...
51 416
Александр Красильников "размер структуры всегда ЧЕТНЫЙ размеру наибольшего базового типа" - в смысле кратный?
Похоже так и есть. Добавил еще один "int" и общий размер остался 40 байт. Либо если заменить один "int" на указатель, тоже останется 40 байт. Т.е. эти 4 байта лишних просто не используются. Спасибо.
Тебе все правильно про выравнивание сказали. Не забывай, что хотя компилятор сам подбирает, как ему выравнивать данные, ему можно и помочь. Или помешать. Сравни:
1)
 struct elem 
{
int sunsж
int num;
elem *next;
} *head;
sizeof этого чуда будет 16 байт: первые 2 инта объединились в 8 байт + 8 байт указатель
2)
 struct elem 
{
int suns;
elem *next;
int num;
} *head;
А вот у этого чуда sizeof будет уже 24: первый int - 4 байта, но дальше указатель (8), значит эти 4 байта не с кем объединить и того получится 4 байта инт + 4 байта нулей + 8 байт указатель. Аналогично, последний инт не с кем объединить - так что он все 8 байт займет
3)
 struct elem 
{
int suns;
elem *next;
int num;
int val;
} *head;
А вот тут мы еще инт в конец добавили - и их можно объединить вместе, так что sizeof все еще 24 байта
4)
 struct elem 
{
int suns;
int other;
elem *next;
int num;
int val;
} *head;
А вот тут и первый инт есть с кем объединить - будет 24 байта без потерь на выравнивание

Или просто увеличь в своем примере строку до 24 символов - sizeof все еще 40 будет, просто теперь 4 байта не забиты нулями из-за выравнивания. А увеличишь до 25 - все, sizeof 48, из них - 7 байт нулей для выравнивания строки