Почему эта программа на C ++ возвращает 16 байтов?

0

Приведенная ниже программа при компиляции с использованием gcc и выполняется в 32-битной архитектуре возвращает 16 байт. Мне интересно, почему он возвращается, так как он не использует длинный двойной член или не работает на 64-битной машине, и нет виртуальных функций, определенных для получения дополнительных байтов памяти и при вычислении размера данных double и int член, результат составляет около 12 байтов. Итак, почему это значение составляет 16 байтов?

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x4601a8
     foo *f = new (obj) foo; // Custom operator new called for **16 bytes**
                                       // foo constructor called (this=0x4601a8)
     printf("foo allocated at %p\n", f); // foo allocated at 0x4601a8
}
  • 1
    Там может быть безымянный отступ в объекте структуры
  • 0
    Зависит от вашей упаковки по умолчанию - с 1, 2 или 4 байтовой упаковкой вы получите 12. С 8 или 16 байтовой упаковкой вы получите 16.
Теги:

5 ответов

4

4 байта добавляются в конце foo качестве дополнения. Обычно это делается для целей выравнивания - double выровнено по 8 байтов в вашей архитектуре, поэтому, если вы создаете массив foo s, байты заполнения указывают, что элемент a правильно выровнен.

В классе-типе нет гарантии, что размер равен сумме размеров членов. Чаще всего это не так.

Существуют специальные флаги, зависящие от компилятора, которые не добавляют добавочные байты, которые вы можете найти. (pragma pack)

  • 0
    Да - двойной
0

Это связано с внутренним дополнением, применяемым компилятором. Мы можем избежать этого, используя директиву __packed compiler.

Вы можете сослаться на следующее сообщение, чтобы узнать о дополнении

Прокладка и упаковка структуры

0

Рассмотрим выравнивание данных. Компилятор выравнивает данные объекта в другом, чтобы сохранить их в памяти, чтобы процессор мог получить их в одной загрузке - это возможно только для выровненных данных. Это аппаратный аспект.

0

когда я запускаю свой код, который я нашел в следующем:

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x991d008
     printf("size of obj: %d\n", sizeof(obj)); // size of obj:  4
     printf("size of foo: %d\n",sizeof(foo)); // size of foo: 12
     foo *f = new (obj) foo; // Custom operator new called for **12 bytes**
                                       // foo constructor called (this=0x991d008)
     printf("foo allocated at %p\n", f); // foo allocated at 0x991d008
} 

Я добавил два дополнительных оператора печати, здесь размер foo равен 12. Это double + int.

  • 0
    Заполнение зависит от системы, поэтому, к сожалению, это не очень полезно. Код даст разные результаты на разных компьютерах и компиляторах.
0

В структурном объекте может быть неназванное дополнение, которое называется Data_structure_alignment

в вашем случае double выравнивается до 8 байтов, поэтому sizeof foo должен быть 8 * N, поэтому 4 байта заполнены

Ещё вопросы

Сообщество Overcoder
Наверх
Меню