Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной структуры данных (может, макрос или хидер).
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).минимальный - sizeof(void *)
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).pow(2, ceil(log2(sizeof(x)))) вроде же
у gcc есть __alignof__
Нашёл в /usr/include/bits/wordsize.h константу __WORDSIZE. Правда оно в битах, но тоже подходит.
А sizeof(void*) на других платформах (например arm atmega) корректно работает?
> Нашёл в /usr/include/bits/wordsize.h константу __WORDSIZE. Правда оно в битах, но тоже
> подходит.
> А sizeof(void*) на других платформах (например arm atmega) корректно работает?Корректно.
Слушай, граница выравнивания для разных типов данных и/или на разных платформах разная.
Например для х86:sizeof(char) == 1, граница 1
sizeof(short) == 2, граница 2
sizeof(int) == 4, граница 4
sizeof(double) == 8, граница 8
sizeof(long double) == 10, граница 16, т.к. особо указано в интеловском мануале
sizeof(long long) == 8, граница 4, т.к. для не-FPU/SSE типов граница всегда <= 4Невыровненные обращения ведут к:
а) падению производительности (засчет двух чтений вместо одного, ну или трех вместо двух)
б) фолту по невыравненному обращению, если включен таковой флаг в MSW/...sizeof() структуры вообще может быть 57, и выравнивать ее больше, чем на long double, т.е. 16, не имеет смысла, кроме случаев, когда хочется попасть на границу кеш-линии, но это другая история, причем непереносимая даже внутри одной линейки процессоров.
Ты точно ту проблему решаешь?
>[оверквотинг удален]
> sizeof(short) == 2, граница 2
> sizeof(int) == 4, граница 4
> sizeof(double) == 8, граница 8
> sizeof(long double) == 10, граница 16, т.к. особо указано в интеловском мануале
> sizeof(long long) == 8, граница 4, т.к. для не-FPU/SSE типов граница всегда
> <= 4
> Невыровненные обращения ведут к:
> а) падению производительности (засчет двух чтений вместо одного, ну или трех вместо
> двух)
> б) фолту по невыравненному обращению, если включен таковой флаг в MSW/...Это всё понятно.
> sizeof() структуры вообще может быть 57,
Честно говоря, я не представляю sizeof() структуры == 57, ну разве что "поучить" компилятор с помощью #pragma pack или align директив. Тогда да, возможно всё. Я это не спора ради, так, мысли вслух.
> и выравнивать ее больше, чем на
> long double, т.е. 16, не имеет смысла, кроме случаев, когда хочется
> попасть на границу кеш-линии, но это другая история, причем непереносимая даже
> внутри одной линейки процессоров.
> Ты точно ту проблему решаешь?Точно ту. Поясню. Есть шаряная память, в котороу я кладу различные структуры, а также массивы типа unsigned char с переменной длиной. Со структурами всё хорошо, они выровненные, никаких проблем не доставляют. А вот массивы unsigned char нужно ручками выравнивать (т.е. добавлять в конце несколько байт), чтобы в памяти следующие за этим массивом структуры или другие массивы после выполнения mmap() имели корректную адресацию. Ещё нюанс, софтина должна уметь работать на x86, x86_64 и arm. Поэтому и озадачился выравниваниями. (про atmega я спросил для общего развития, к вопросу она не имеет отношения).
В общем, спасибо за совет, буду использовать sizeof(void*).
>> sizeof() структуры вообще может быть 57,Например struct { char a[56]; char c; }, хотя согласен, пример идиотский.
Для struct { short a[28]; char c; } будет уже 58.
Для struct { int a[14]; char c; } будет 60, ну теперь-то идея понятна...> В общем, спасибо за совет, буду использовать sizeof(void*).
...нужно в структуре визуально найти самый большой по sizeof'у член и выровнять по его границе. Если решение кажется error-prone, например есть структуры в структурах в структурах, можно использовать это:
union {
intmax_t i;
long double ld;
void *p;
};Ее sizeof есть максимальная граница выравнивания для ISO C99.
> union {
> intmax_t i;
> long double ld;
> void *p;
> };
> Ее sizeof есть максимальная граница выравнивания для ISO C99.Можно и так, но, думаю, можно обойтись просто sizeof(void*). Главная цель: чтобы при обращении к данным (структурам и массивам) из некоторой области shared memory, отображённой в адресное прастранство процесса, процесс обращался к корректным адресам. Т.е. чтобы в отображённом куске shared memory начала структур и массивов имели корректные адреса. Например, на arm'ах (может не на всех, точно не знаю) запрещено обращаться к нечётным адресам, arm генерит исключение при обращении к нечётным адресам. Может linux и умеет разруливать такие ситуации на arm, но не хотелось бы тратить на это процессорное время. Лучше софтину написать с учётом таких особенностей. Думаю, выравнивание данных до размера, кратного sizeof(void*), достаточно и универсально для всех современных архитектур. По крайней мере, для тех трёх, что я указал выше, точно подойдёт.
>> union {
>> intmax_t i;
>> long double ld;
>> void *p;
>> };
>> Ее sizeof есть максимальная граница выравнивания для ISO C99.
> Можно и так, но, думаю, можно обойтись просто sizeof(void*). Главная цель: чтобы
> при обращении к данным (структурам и массивам) из некоторой области shared
> memory, отображённой в адресное прастранство процесса, процесс обращался к корректным
> адресам.Расскажите, что такая за программулина, которой нужно обращение к корректным адресам?!
Потом я Вам расскажу, единственное место в современном мире где используется выравнивание.
Нет, оно конечно не единственное, есть и более спец. задачи, но те люди которым это нужно
на сайте для лохов не пишут.
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).Для выравнивания структуры обычно используют ключевое слово __attribute__
для запаковки структуры с параметром ((__packed__))
пример:
struct my_packed_struct __attribute__ ((__packed__))
{
char c;
short int i;
};такая структура занимает 3 байта.
больше информации http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes....