Размер структуры с char, double, int и at [duplicate]

20
задан Max Galkin 30 December 2016 в 20:07
поделиться

9 ответов

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

struct {
  char a;
  void* b;
};

, то b не может использовать сумматор №1 - он должен быть размещен в №4.

  0   1   2   3   4   5   6   7
+---+- - - - - -+---------------+
| a | (unused)  | b             |
+---+- - - - - -+---------------+

В вашем случае дополнительные 7 байтов поступают из 3 байтов из-за выравнивания int * и 4 байтов из-за выравнивания double .

  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
+---------------+---+- - - - - -+---------------+- - - - - - - -+
| i             |ch |           | p             |               |
+---------------+---+- - - - - -+---------------+- - - - - - - -+
 10  11  12  13  14  15  16  17
+-------------------------------+
| d                             |
+-------------------------------+
52
ответ дан 29 November 2019 в 22:40
поделиться

... это дает мне 24, и я сбит с толку. Каковы дополнительные 7 байтов?

Это байты заполнения, вставленные компилятором. Заполнение структуры данных зависит от реализации.

Из Википедии, Выравнивание структуры данных :

Выравнивание данных означает размещение данных со смещением памяти, равным некоторому кратному размеру слова, что увеличивает производительность системы из-за способа обработки ЦП объем памяти. Чтобы выровнять данные, может потребоваться вставить несколько бессмысленных байтов между концом последней структуры данных и началом следующей, что является заполнением структуры данных.

9
ответ дан 29 November 2019 в 22:40
поделиться

Чтобы немного расширить отличный ответ KennyDM (Кенни - пожалуйста, укради это, чтобы дополнить свой ответ, если хотите), это, вероятно, то, что вам запомнилось структура выглядит так, как только компилятор выровнял все переменные:

  0    1    2    3    4    5    6    7
+-------------------+----+-----------+
| i                 | ch | (unused)  |
+-------------------+----+-----------+

  8    9   10   11   12   13   14   15
+-------------------+----------------+
| p                 |   (unused)     |
+-------------------+----------------+

 16   17   18   19   20   21   22   23
+------------------------------------+
| d                                  |
+------------------------------------+

Итак, из-за 3-байтового разрыва между «ch» и «p» и 4-байтового разрыва между «p» и «d», вы получаете 7-байтовый отступ для вашей структуры, таким образом, размер 24 байта. Поскольку ваша среда double имеет 8-байтовое выравнивание (то есть он должен находиться в собственном 8-байтовом блоке, как вы можете видеть выше), вся структура также будет 8- байт выровнен полностью, поэтому даже переупорядочение переменных не изменит размер с 24 байтов.

8
ответ дан 29 November 2019 в 22:40
поделиться

Компилятору разрешено выравнивать элементы структуры по адресам для более быстрого доступа. например 32-битные границы. Стандарт требует только, чтобы члены объекта хранились в том порядке, в котором они объявлены. Поэтому всегда убедитесь, что вы используете sizeof и offsetof , когда вам нужна точная позиция в памяти.

0
ответ дан 29 November 2019 в 22:40
поделиться

$ 9.2 / 12 заявляет - «Нестатические элементы данных класса (не-объединения), объявленные без промежуточного спецификатора доступа, выделяются так, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных, разделенных спецификатором доступа, не определено (11.1). Требования к согласованию реализации может привести к тому, что два соседних элемента не будут размещены сразу после друг друга; так может требования к пространству для управления виртуальными функциями (10.3) и виртуальными базовыми классами (10.1). "

Так же, как sizeof (double) и sizeof (int), смещения, по которым будут выровнены элементы структуры, не определены, за исключением того, что члены, объявленные позже, находятся по более высоким адресам.

0
ответ дан 29 November 2019 в 22:40
поделиться

Дополнительный размер возникает из-за выравнивания данных, т.е. члены выравниваются по кратным 4 или 8 байтам.

Ваш компилятор, вероятно, выравнивает int и указатели по кратным 4 байтам, а double - по кратным 8 байтам.

Если вы переместите double в другую позицию внутри struct, вы сможете уменьшить размер struct с 24 до 20 байт. Но это зависит от компилятора.

0
ответ дан 29 November 2019 в 22:40
поделиться

Также иногда вам может понадобиться структура для поддержания необходимого вам порядка. В этом случае, если вы используете gcc, вы должны использовать оператор __ attribute __ ((pack)) .

См. Также для получения дополнительной информации.

0
ответ дан 29 November 2019 в 22:40
поделиться

Это 24 байта из-за заполнения. Большинство компиляторов дополняют данные до кратного их размера. Итак, 4-байтовое int дополняется до числа, кратного 4 байтам. 8-байтовое двойное значение дополняется до числа, кратного 8 байтам. Для вашей структуры это означает:

struct struct_type{
  int i; // offset 0 (0*4)
  char ch; // offset 4 (4*1)
  char padding1[3];
  int *p; // offset 8 (2*4)
  char padding1[4];
  double d; // offset 16 (2*8)
}s;

Вы можете оптимизировать вашу структуру следующим образом:

struct struct_type{
  double d;
  int i;
  int *p;
  char ch;
}s;

sizeof (s) == 17 в большинстве компиляторов (20 в некоторых других)

1
ответ дан 29 November 2019 в 22:40
поделиться

См. список FAQ по comp.lang.c - Вопрос 2.12:

Почему мой компилятор оставляет дыры в структурах, теряя место и предотвращая ``бинарный'' ввод/вывод во внешние файлы данных? Могу ли я отключить это или иным образом контролировать выравнивание полей структуры?

0
ответ дан 29 November 2019 в 22:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: