LINUX.ORG.RU

Есть ли выравнивание данных в C/C++ структурах?


0

0

может ли C/C++ иметь «своё мнение» относительно данных в структуре, то есть, например, если идёт {uint8, uint8, uint8, uint32} вставить лишний байт перед uint32 «для ровного счёту» или ещё что-нибудь?

ну например

typedef struct {
uint64 root_rowid_tail;
uint16 type_id;
uint8 node_slots;
uint32 table_object_id;
uint32 next_index_object_id;
uint16 colnumber;
uint16 index_name_size;
} Tindexinfo_header;

★★★

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

Кому это не нравится, тот должен использовать pragma packed.

anonymous
()
uint8 *t=(uint8*)(&(e->indexinfo_header->table_object_id));
printf("сдвиг=%lld\n",t-(uint8*)e->indexinfo_header);

сдвиг=12

Теперь вопрос - как с этим жить?

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh
struct test_t {
  int  a;
  char b;
  int  c;
} __attribute__((__packed__));

struct test_t test = { 10, 20, 30};

Угу. вот так. только непонятно что мне делать с этим дальше :)

vahvarh ★★★
() автор топика

Мужик, повторяю еще раз тут.

У тебя структура выравнена по DWORD. Это делается для того, что бы ты имел доступ к памяти вообще (в нормальных процессорах) и быстрый в intel.

Если ты расчитываешь только на intel, то можешь брать pragma paked, но про перфоманс можешь забыть.

Да и как про попытку собрать это на чем-то отличном от intel.

catap ★★★★★
()
Ответ на: комментарий от vahvarh

Ээээээ мне тут из зала подсказывают что на arm/atom/mips такое сделать нельзя:

uint8 *data=malloc(1000);
((uint32*)(data+3))[0]=1;
ибо оно не выравнено по dword

правда ли это?

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh

> правда ли это?

подтверждаю, сегфолтится. с не выровненными полями структур, ЕМНИП, нет такого: компилятор всё знает и генерирует код для побайтной записи/чтения в кривые поля.

arsi ★★★★★
()
Ответ на: комментарий от vahvarh
#include <stdio.h>
#include <stdlib.h>

#define uint8 unsigned char
#define uint32 unsigned int
int main(int argc,char **argv)
{

	uint8 *data=malloc(1000); 
	((uint32*)(data+3))[0]=1;
}
vahvarh ★★★
() автор топика
Ответ на: комментарий от tailgunner

угу. умный? ну дай мне готовый storage-backend. и опять же, не забудь про всякую фигню с этим связанную. всё равно когда из него данные достаёшь их парсить как-то надо.

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh

> угу. умный?

Можешь считать меня трусом, если хочешь.

ну дай мне готовый storage-backend

SQLite? BerkeleyDB? Что-то Erlang-специфичное?

и опять же, не забудь про всякую фигню с этим связанную

Про фигню не знаю, но по крайней мере с индексы там уже реализовали.

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

tailgunner ★★★★★
()
Ответ на: комментарий от catap

> в erlang очень мило указанный мной innodb впиливается и получается много счастья!

По мне, так он большой слишком и избыточный, но это всё равно лучше, чем свой писать.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Опять же, ещё вопрос будет ли беркли переноситься с одной платформы на другую. Хотя конечно взять беркли мысль заманчивая.

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh

просто опять же, если мне нужно сделать индексы по таблице то мне придётся делать для каждого индекса по берклёвому хешу

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh

и я правильно понял что я тогда не смогу сделать closed source?

vahvarh ★★★
() автор топика
Ответ на: комментарий от vahvarh

> не хочу я брать эрланг.

O_o

и я правильно понял что я тогда не смогу сделать closed source?

Думаю, и для BDB, и для InnoDB можно договориться о не-GPL лицензии.

А вот чтобы закрыть SQLite, договариваться ни с кем не надо :)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

bdb и innodb (сюрпрайз) принадлежат ораклу. с ним договариваться очень просто - $5800/ядро_процессора.

erlang - я как нашёл его особенности работы с памятью так вся любовь и закончилась. он если не может выделить память то валится полностью, всей виртуальной машиной.

vahvarh ★★★
() автор топика
Ответ на: комментарий от tailgunner

ну вообще это известная фича эрланга

vahvarh ★★★
() автор топика

И, знаешь, теперь уже совсем ясно - никакую СУБД ты не напишешь. Зря стараешься.

anonymous
()
Ответ на: комментарий от madcore

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

проще использовать кодогенератор, из того же ASN.1.

Begemoth ★★★★★
()
Ответ на: комментарий от vahvarh

> то есть оно при выполнении этого кода даёт sefault?

да не помню я, какое именно прерывание оно возбуждает :) там вообще ucos был, не линукс, да и набор исключений там другой… я лично с армами не работал, только с мипсами (кроме х86), просто видел этот прикол у сотрудника, который портировал на арм одно наше приложение; он ещё на этот нюанс на перекурах жаловался, с матами и прочим, поэтому и запомнил ;)

тоесть да, код, который вызвал исключение выравнивания на армах, уже не может быть продолжен. в х86 процессорах (начиная, ЕМНИП, с 486) можно было установить флаг выравнивания, при котором при соблюдлении выравнивания получался значительный прирост в производительности в/в с памятью, но при нарушении выравнивания — исключение процессора, но не фатальное, т.е. обработчик исключеия мог обнулить флаг выравнивания прерванного «процесса» и продолжить его выполнение уже без оптимизации выравнивания данных.

arsi ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

>Размер структуры выравнивается на границу 4 байт.

Особенно на 8-битных системах так любят делать...

Но можно установить любое.


Мне плиз 3 бита отмерьте.

madcore ★★★★★
()
Ответ на: комментарий от catap

ASN.1 конечно не получится, но что-то типа Boost.Spirit для двоичных файлов.

Begemoth ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

> Размер структуры выравнивается на границу 4 байт.

4.2. любые данные (кроме кода), выравниваются на адрес, кратный размеру данных. т.е. поле типа int64_t будет выровнено на границу 8 байт. 128-битный float будет выровнен на 16-байтную границу и т.п.

arsi ★★★★★
()

POD структуры выравниваются. Существует единственное правило (точно не приведу), оно зависит только от размера членов (и порядка следование). по моему правило один в один совпадает с С

Если у тебя появится хотя бы один private и аже с ним - компилятор имеет право разложить данные как хочет.

Да. Может и вставить. Но тогда все компиляторы вставят. Вот только переносимости по моему однозначное не будет

namezys ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

> 8 будет, и на х86 и на х86_64

так точно :) проверил пока только на х86_64+gcc и х86_64+sunCC, за другие копмиляторы не ручаюсь. собсно, всё логично: вполне возможно, что тип будут использовать как элементы массива, а сохранять для него выравнивание — дело чести для компилятора. хоть и не для каждого… =( в своё время компилятор от sun меня разочаровал чуть больше, чем полностью: оптимизирует здорово, но криво…

arsi ★★★★★
()
Ответ на: комментарий от namezys

еще раз: компилятор не имеет право изменять выравнивание элементов структуры. это определно в стандарте.

компилятор и не изменяет, это далает тот, кто пишет программу.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от namezys

> компилятор не имеет право изменять выравнивание элементов структуры

изменять выравнивание с какого значения на какое, для каких архитектур и при каких условиях? ;)

> это определно в стандарте

пруфлинк ;)

arsi ★★★★★
()
Ответ на: комментарий от arsi

> пруфлинк ;)

Я немного не в состоянии щас копаться в стандарте

изменять выравнивание с какого значения на какое, для каких архитектур и при каких условиях? ;)

Может, если стуртура не относится к простым.

namezys ★★★★
()
Ответ на: комментарий от namezys

В общем покапавшись в памяти:

варвание члена внутри структуры такое же, как и самого члена отдельно. То есть если он занимает 6 байт, то выравние по 6ке. Далее - массивы не учитываются. То есть если у нас массив из 4 чаров, то выравнивание первого идет как просто чара.

далее. размер структуры точно кратнен самому большому типу. Если не ошибаюсь, то он вообще кратен наименшему общему кратному. Но это не точно.

Выравнивание структуры делается по кратному тоже - так чтоб любой член был выравнен так же, как если бы он был без структуры.

Все это надо, чтоб на некоторых типах процессоров не было лишних прерываний (типа альфы).

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

namezys ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.