Почему sizeof () отличается на 64-битном процессоре? - PullRequest
5 голосов
/ 04 июня 2009

Рассмотрим следующий пример:

#include <stdio.h>
#include <inttypes.h>

struct A {
        uint32_t i1;
        uint32_t i2;
        uint32_t i3;
        uint64_t i4;
        uint32_t i5;
        uint32_t i6;
        uint32_t i7;
        uint64_t i8;
        uint32_t i9;
};

struct B {
        uint32_t i1;
        uint32_t i2;
        uint32_t i3;
        uint32_t i4;
        uint32_t i5;
        uint32_t i6;
        uint32_t i7;
        uint64_t i8;
        uint64_t i9;
};

int
main()
{
        struct A a;
        struct B b;

        printf("sizeof(a) = %u, sizeof(b) = %u\n", sizeof(a), sizeof(b));

        return 0;
}

Вывод:

$ ./t2 
sizeof(a) = 56, sizeof(b) = 48
$ 

Почему они отличаются на 64-битной машине? На 32-битной платформе результаты такие же:

$ ./t2
sizeof(a) = 44, sizeof(b) = 44

Ответы [ 8 ]

22 голосов
/ 04 июня 2009

Некоторые диаграммы, которые помогут вам увидеть:

32-бит:

+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 |   i4    | i5 | i6 | i7 |   i8    | i9 | Struct A
+----+----+----+----+----+----+----+----+----+----+----+

+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 |   i8    |   i9    | Struct B
+----+----+----+----+----+----+----+----+----+----+----+

64-бит:

+---------+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 |~~~~|    i4   | i5 | i6 | i7 |~~~~|   i8    | i9 |~~~~| Struct A
+---------+---------+---------+---------+---------+---------+---------+

+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 |~~~~|   i8    |   i9    | Struct B
+---------+---------+---------+---------+---------+---------+
  • + : границы адресов
  • ~ : отступ
8 голосов
/ 04 июня 2009

Компилятор выравнивает элементы структуры по границе (которая отличается в ваших попытках компиляции).

Добавить

#pragma pack (1)

директива в начале исходного файла и повторите попытку.

3 голосов
/ 04 июня 2009

Потому что может. Компилятору не требуется использовать одну и ту же компоновку между 32 и 64-битным режимом. Он может вставить отступ, когда захочет. Вы не должны полагаться на точное расположение структуры в первую очередь.

В принципе, он может даже изменять отступ при каждой компиляции. (Трудно представить, почему компилятор сделал бы это, но это разрешено)

2 голосов
/ 04 июня 2009

64-битные целые должны быть размещены на границе 64-битной памяти. Таким образом, при создании структуры A на 64-битной машине компилятор вставляет 4-байтовое пространство заполнения после i3 и i7 - таким образом добавляя туда дополнительные 8 байтов.

1 голос
/ 04 июня 2009

Это вызвано выравниванием структуры: struct A имеет 3 32-битных значения, за которыми следует 64-битное. Независимо от упаковки первых 3 элементов, 64-битный элемент определенно не будет начинаться между границами (то есть занимать половину двух отдельных 64-битных значений) на 64-битном, поэтому между 3-м и 4-м элементом есть как минимум 32-битное заполнение.

1 голос
/ 04 июня 2009

Из-за заполнения между элементами.

0 голосов
/ 04 июня 2009

Это из-за выравнивания.

Возможно, что 64-разрядные целые числа на вашей платформе должны быть выровнены на 64-разрядные.

Итак, в смешанной структуре у вас есть 3 32-битных целых числа, после них должен быть вставлен другой 32-битный отступ, чтобы правильно выровнять 64-битное целое число.

Разница в размере должна исчезнуть, если вы вставите четное число из 32-битного поля перед вашим 64-битным полем.

0 голосов
/ 04 июня 2009

sizeof (b) равно 48, потому что последний uint32 занимает целые 64-битные (потому что последующие uint64 выровнены по 64-битным блокам. Sizeof (a) занимает больше, потому что первые 3 unit32 занимают 2 блока следующие 3 занимают 2 блока, а финальный uint32 занимает полный 64-битный блок

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...