В частности, это возникло в дискуссии:

В отношении потребления памяти, есть ли вероятность, что использование struct из двух int файлов займет больше памяти, чем просто два int?

Или в языковых терминах:

#include <iostream>

struct S { int a, b; };

int main() {
    std::cout << (sizeof(S) > sizeof(int) * 2 ? "bigger" : "the same") << std::endl;
}

Существует ли какая-либо разумная 1 (не обязательно общепринятая или текущая) среда, в которой эта маленькая программа напечатает bigger?

1

21
Bartek Banachewicz 4 Сен 2017 в 15:49

4 ответа

Было бы совершенно неправдоподобно, что система, которая может получить доступ к памяти только в 64-битных блоках, могла бы иметь возможность использовать 32-битный размер «int» для совместимости с другими программами, которые могли бы получить срабатывание uint32_t, что повышает его тип. , В такой системе структура с четным числом значений типа «int», скорее всего, не будет иметь дополнительного заполнения, но структура с нечетным числом значений может, вероятно, сделать это.

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

2
supercat 4 Сен 2017 в 20:12

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

0
Rohit 4 Сен 2017 в 14:12

Я знаю, что это не то, что вы просили, это не в духе вашего вопроса (поскольку вы, вероятно, имеете в виду стандартные классы макетов), но строго отвечая только на эту часть:

В отношении потребления памяти, существует ли вероятность, что использование структуры из двух целых занимает больше памяти, чем просто две?

Ответ вроде ... да

struct S
{
    int a;
    int b;

    virtual ~S() = default;
};

с педантичным примечанием, что C ++ не имеет структур, у него есть классы. struct - это ключевое слово, которое вводит объявление / определение класса.

2
bolov 4 Сен 2017 в 18:02

В вашем конкретном примере struct S { int a, b; }; я не вижу никаких разумных аргументов для заполнения. int должен быть уже естественно выровнен, и если это так, int * может и должен быть естественным представлением для указателей, и нет необходимости в том, чтобы S * отличались. А вообще:

Несколько редких систем имеют указатели с разными представлениями, например, int * представляется как целое число, представляющее адрес «слова», а char * представляет собой комбинацию адреса слова и байтового смещения в этом слове (где байтовое смещение сохраняется в ненужных старших битах, в противном случае слова адрес). Разыменование char * происходит в программном обеспечении, загружая слово, а затем маскируя и сдвигая, чтобы получить правильный байт.

В таких реализациях может иметь смысл обеспечить минимальное выравнивание всех типов структуры, даже если это не является обязательным для элементов структуры, просто для того, чтобы беспорядок смещения в байтах не был необходим для указателей на эту структуру. Это разумно, учитывая struct S { char a, b; };, sizeof(S) > 2. В частности, я бы ожидал sizeof(S) == sizeof(int).

Я никогда лично не работал с такими реализациями, поэтому я не знаю, действительно ли они производят такие дополнения. Но реализация, которая делает это, была бы разумной и, по крайней мере, очень близкой к существующей реальной реализации.

3
4 Сен 2017 в 19:26