_NN>Есть ли способ указать, чтобы после 'a' гарантированно не было выравнивания в классах B и C? _NN>Желательно без изменений этих классов.
Добавление __attribute__((__packed__)) считается изменением класса?
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
_NN>>Есть ли способ указать, чтобы после 'a' гарантированно не было выравнивания в классах B и C? _NN>>Желательно без изменений этих классов. O>Добавление __attribute__((__packed__)) считается изменением класса?
Классу A можно добавлять что угодно.
А если есть ещё и стандартное решение будет совсем круто.
Здравствуйте, _NN_, Вы писали:
_NN>Есть ли способ указать, чтобы компилятор не вставлял выравнивание во внешнем объекте ?
Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop)
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, _NN_, Вы писали:
_NN>>Есть ли способ указать, чтобы компилятор не вставлял выравнивание во внешнем объекте ?
Pzz>Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop)
Проблема в том, что это надо делать для B и C и любого класса который имеет члена типа A, а я хочу чтобы не нужно было это повторять
Здравствуйте, _NN_, Вы писали:
Pzz>>Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop) _NN>Проблема в том, что это надо делать для B и C и любого класса который имеет члена типа A, а я хочу чтобы не нужно было это повторять
Но это единственный доступный способ
Если цель серриализация, то как мне кажется, лучше использовать что-то типа Protobuf, нежели с выравниванием заморачиваться.
Здравствуйте, kaa.python, Вы писали:
KP>Здравствуйте, _NN_, Вы писали:
Pzz>>>Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop) _NN>>Проблема в том, что это надо делать для B и C и любого класса который имеет члена типа A, а я хочу чтобы не нужно было это повторять
KP>Но это единственный доступный способ KP>Если цель серриализация, то как мне кажется, лучше использовать что-то типа Protobuf, нежели с выравниванием заморачиваться.
Цель улучшить язык
Есть много типов, для которых хотелось бы гарантировать размер, скажем: unique_ptr, array и т.д.
Хочется иметь гарантию, что замена указателя на unqiue_ptr или массива на std::array не отразиться на размере типа.
Здравствуйте, _NN_, Вы писали:
Pzz>>Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop) _NN>Проблема в том, что это надо делать для B и C и любого класса который имеет члена типа A, а я хочу чтобы не нужно было это повторять
Посмотри опции компилятора. У GCC есть опция -fpack-struct[=n] . У других компиляторов, вроде бы, тоже есть параметры, что бы задать выравнивание. Если задано выравнивание и опцией сборки и #pragma pack, то используется #pragma pack.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, _NN_, Вы писали:
_NN>>Цель улучшить язык
R>Да признайся уже, реинтерпреткастишь? Мы поймем и простим
Как раз он не при чём.
Скажем есть у меня:
template<typename T, size_t N> struct array { T elems[N]; };
Используется просто:
class X
{
array<int, 10> a;
};
Я бы хотел, чтобы компилятор гарантировано интерпретировал его как:
class X
{
int a[10];
// выравнивание класса X
};
Сейчас теоретически это выглядит так:
class X
{
int a[10];
// внутреннее выравнивание array<int, 10>
// выравнивание класса X
};
Здравствуйте, _NN_, Вы писали:
_NN>Скажем есть у меня: _NN>Используется просто: _NN>Я бы хотел, чтобы компилятор гарантировано интерпретировал его как: _NN>
_NN>class X
_NN>{
_NN> int a[10];
_NN> // выравнивание класса X
_NN>};
_NN>
Да цель твоя понятна. Не понятно, почему это так важно для тебя.
Здравствуйте, _NN_, Вы писали:
Pzz>>Стандартного (т.е., описанного в каком-либо стандарте) решения нет, но многие компиляторы понимают #pragma pack (1) или #pragma pack (push, 1)/#pragma pack (pop) _NN>Проблема в том, что это надо делать для B и C и любого класса который имеет члена типа A, а я хочу чтобы не нужно было это повторять
Опыт показывает, что если набивать структуры аккуратно, расставляя 2/4/8-байтовые типы по правильно выровненным позициям (и добавляя по мере необходимости явные поля для заполнения дыр) можно добиться того, что компилятор не будет трогать выравнивание. При этом лучше использовать типы навроде uint32_t или int64_t, а не int и long.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, _NN_, Вы писали:
_NN>>Скажем есть у меня: _NN>>Используется просто: _NN>>Я бы хотел, чтобы компилятор гарантировано интерпретировал его как: _NN>>
_NN>>class X
_NN>>{
_NN>> int a[10];
_NN>> // выравнивание класса X
_NN>>};
_NN>>
R>Да цель твоя понятна. Не понятно, почему это так важно для тебя.
Ну как почему, производительность
Например я делаю обёртку для ссылки, чтобы класс стал некопируемым и я хочу, чтобы это не влияло на размер класса.
Можно конечно в сам класс добавлять необходимые функции явно, но хочется удобства.
struct A
{
A(int& i):i(i) {}
int& i;
// неявно копируется
};
template<typename T>
struct non_copyable_ref
{
non_copyable_ref(T& value):value(value) {}
non_copyable_ref(non_copyable_ref const&) = delete;
non_copyable_ref& operator=(non_copyable_ref const&) = delete;
T& value;
};
struct B
{
B(int& i):i(i) {}
non_copyable_ref<int> i;
// неявно не копируется
};
int main()
{
int i;
A a1(i);
A a2(a1);
B b1(i);
B b2(b1); // Error
}
Здравствуйте, _NN_, Вы писали:
R>>Да цель твоя понятна. Не понятно, почему это так важно для тебя.
_NN>Ну как почему, производительность
Производительность при нарушении выравнивания ? Оригинально-с!
Более того, есть архитектуры, которые принципиально не умеют обращаться к невыровненным данным. ARM например.
Интел тоже умеет генерировать исключение при невыровненном доступе. Но рукожопов слишком много, так и не взлетело.
Здравствуйте, IID, Вы писали:
IID>Производительность при нарушении выравнивания ? Оригинально-с!
Проблема не с выравниванием, а с размером объекта.
Я хочу иметь гарантии, что мой объект будет располагаться также как если бы я скопировал все члены класса во внешний класс.
Т.е.
[[какой-нибудь-атрибут]]
class A { int* p; int x; };
class B { A a; int y; };
// Гарантировано будет расположен в памяти какclass B { int* p; int x; int y; };
// , а не как позволительно компилятора вродеclass B { int* p; int x; int padding_after_a; int y; };