Возникла одна трабла по С. В UNIX я слабак, раньше программил под Вындовс. Может быть кто то сталкивался с этой проблемой. Мне нужно считать массив char в структуру. Делаю примерно так.char arr[100];
struct mystruct
{
char a, int b;
};struct mystruct *st = (struct mystruct *)arr;
теперь &(st->a) будет = &arr[0], а &(st->b) = &arr[4]
а нужно что бы &(st->b) ссылался на &arr[1].Как это сделать? Я знаю что в масдаях есть директива компилятора, которая выравнивает структуры по байтам. Как это сделать в gcc? Есть ли такая директива компилятора? Или может быть кто то знает другой эффективный способ корректного наложения структуры на массив?
Заранее благодарен за ответы.
#pragma pack(N), в твоем случае N=1 :)
>#pragma pack(N), в твоем случае N=1 :)Ага, спасибо. Я уже так и сделал и все заработало. Скажите, а на сколько в этом случае упадет производительность? Если я скомпилирую gcc -с -o myfile.o mysile.c, повлияет ли эта дирректива на всю программу или только на объектный файл myfile.o?
>>#pragma pack(N), в твоем случае N=1 :)
>
>Ага, спасибо. Я уже так и сделал и все заработало. Скажите, а
>на сколько в этом случае упадет производительность? Если я скомпилирую gcc
>-с -o myfile.o mysile.c, повлияет ли эта дирректива на всю программу
>или только на объектный файл myfile.o?Я бы компилировал с использованием оптимизатора:
-с -O -o myfile.o mysile.c
>на сколько в этом случае упадет производительность?операция выборки выравненый ячеек в памяти насколько я помню быстрее, но это разница на современных потомках 8080 изчезающе мала :)
>Если я скомпилирую gcc -с -o myfile.o mysile.c, повлияет ли эта дирректива на всю программу или только на объектный файл myfile.o?
#pragma pack(1)
/* выравнивание по байту */
struct ...#pragma pack()
/* выравнивание по умолчанию :) */
Вспоминая содержимое книги Криса Касперски "Техника оптимизации программ.Эффективное использование памяти",- потери при невыравнивании не такие уж и незначительные...
А можно и так:#pragma pack(push, 1)
/* выравнивание по байту */
struct ...#pragma pack(pop)
/* вернули как раньше было */
>>#pragma pack(N), в твоем случае N=1 :)
>
>Ага, спасибо. Я уже так и сделал и все заработало. Скажите, а
>на сколько в этом случае упадет производительность? Если я скомпилирую gcc
>-с -o myfile.o mysile.c, повлияет ли эта дирректива на всю программу
>или только на объектный файл myfile.o?Есть такой тонкий момент, что теперь тебе (без очень тонкой настройки кода) заказана работа с нативными GCC'шными STL-контейнерами, содержащими эту структуру, т.к. у них STL'ные либы имеют предкомпиленные (и предкомпиленные безо всяких pragma pack'ов) куски, которые начинают конфликтовать с шаблонными декларациями в твоей проге, короче все кончается очень плохо, абсолютно неразгребаемыми segfault'ами. Девелоперы GCC сказали что эту багу они править не собираются, ибо "использовать в 21ом веке пакованные структуры - это дикость"...
По той же причине очень не рекоммендуется собирать STL'ный плюсовый софт с помощью g++ -fno-pack
union ff {
char* p;
mystruct *ms;
} myunion;myunion.p = arr;
...или
union ff {
char arr[100];
mystruct *ms;
} myunion;
IMHO это самое корректное решение
struct mystruct
{
char a __attribute__((packed));
int b __attribute__((packed));
};Это просто выровнит одну структуру по размеру.
а #pragma pack(1) выровниит все программу и
уменьшив быстродействие.
> struct mystruct
>{
> char a __attribute__((packed));
> int b __attribute__((packed));
>};
>
> Это просто выровнит одну структуру по размеру.
> а #pragma pack(1) выровниит все программу и
> уменьшив быстродействие.Неа, если писать:
#pragma pack(push,1)
struct _mystruct {
char a;
int b;
};
#pragma pack(pop)
то не все программу, а только конкретную структуру.Если не поймет, то старая запись:
#pragma pack(1)
struct _mystruct {
char a;
int b;
};
#pragma pack()
Вообще-то правильней использовать __attribute__ так:
struct mystruct {
char a;
int b;
} __attribute__((packed));
При упаковке отдельных элементов результат может отличаться от упаковки всей структуры?Использование __attribute__ непереносимо под другие компиляторы.
А вот если забыть закрывающий pack, то первый же виртуальный класс выдаст segmentation fault. STL например ))...
Касперски конечно надо почитать... А лучше заранее подумать над алгоритмом. Тогда и оптимизировать не надо будет :)
"использовать в 21ом веке пакованные структуры - это дикость"...
использовать оператор goto тоже, вот только в некоторых случаях лучше выхода чем оператор goto или пакованные структуры еще не придумали.union тоже выравнивается, так что тоже в pack запихивать надо :)