Подтвердить что ты не робот

Есть ли среда, в которой "int" может вызвать прописку?

В частности, это обсуждалось:

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

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

#include <iostream>

struct S { int a, b; };

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

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

1 Чтобы пояснить, что я имел в виду здесь, это системы (и компиляторы), разработанные и выпущенные в каком-то значимом количестве, а конкретно не теоретические примеры, построенные только для доказательства точечных или одноразовых прототипов или хобби.

4b9b3361

Ответ 1

Есть ли разумная (не обязательно общая или текущая) среда, где эта небольшая программа будет печатать больше?

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

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

  • (1) массивы не могут иметь никакого дополнения между элементами из-за способа доступа к ним с помощью указателей ref;
  • (2) стандартные структуры компоновки могут иметь или не иметь прописку после каждого элемента, но не в начале, потому что они совместимы с макетами с более короткими стандартными структурами компоновки ref;
  • (3) элементы массива и элементы структуры правильно выровнены ref;

Из (1) и (3) следует, что выравнивание типа меньше или равно его размеру. Если бы это было больше, массив должен был бы добавить дополнение, чтобы все его элементы были выровнены. По той же причине размер типа всегда является целым, кратным его выравниванию.

Это означает, что в структуре, такой как заданный, второй элемент всегда будет правильно выровнен — независимо от размера и выравнивания ints — если он расположен сразу после первого элемента, то есть интерстициальное заполнение не требуется. В этом макете размер структуры также уже кратен его выравниванию, поэтому не требуется также добавление прокрутки.

Нет стандартного набора значений (размера, выравнивания), которые мы можем выбрать, что делает эту структуру необходимой формой заполнения.

Любое такое дополнение потребует другой цели. Однако такая цель кажется неуловимой. Предположим, что по какой-то причине существует среда, которая нуждается в этом дополнении. Какова бы ни была причина заполнения, это, скорее всего, и ddagger; также применимы в случае массивов, но из (1) мы знаем, что он не может.

Но предположим, что такая среда действительно существует, и нам нужен компилятор С++. Он может поддерживать это дополнительное требуемое заполнение в массивах, просто делая ints больше, чем много, т.е. Помещая прописку внутри int. Это, в свою очередь, еще раз позволит структуре быть того же размера, что и два ints, и оставить нас без повода для добавления дополнений.


& крестик; Компилятор, даже один, не соответствующий стандарту /mdash, который получает какие-либо из этих ошибок, возможно, ошибочен, поэтому я проигнорирую их.

& ddagger; Я предполагаю, что в среде, где массивы и структуры являются примитивами, может быть какое-то основное различие, которое позволяет нам иметь незакрепленные массивы и заполненные структуры, но опять же, я don ' t знать любую вещь в использовании.

Ответ 2

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

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

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

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

Ответ 3

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

Поглощение памяти мудрый, есть ли вероятность, что использование структуры два ints занимают больше памяти, чем два ints?

ответ прост... да:

struct S
{
    int a;
    int b;

    virtual ~S() = default;
};

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

Ответ 4

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

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

Ответ 5

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