LINUX.ORG.RU

[c] little, big, etc

 


0

0

Поделитесь плиз ссылками на рецепты и правила, как изначально элегантно и эффективно уходить от проблем с эндианами, выравниваниями итп

★★★★★

Хранить инфу в network-ориентировнном виде. При преобразовании к машинному расположению проверять эндиан и менять при необходимости. Я обычно это макросами делаю. С выравниваниями связываться не люблю.

MuZHiK-2 ★★★★
()

используй plain text files для хранения данных — и ни каких проблем с порядком байт у тебя не будет

и до кучи: Writing endian-independent code in C

beastie ★★★★★
()

> как изначально элегантно и эффективно уходить от проблем с эндианами, выравниваниями итп

Просто делать никаких предположений об этих вещах. Внутри одной проги не заглядывать внутрь целочисленных переменных, использовать каждую всегда только целиком и только как целое число. С выравниваниями: считать, что злой компилятор располагает поля в структурах как попало.

const86 ★★★★★
()
Ответ на: комментарий от MuZHiK-2

Хранить изначально не получается, преобразовывать существующие данные кажется накладным.
Пример из пальца:
union{
int8_t r8[32];
int16_t r16[16];
};

Допустим оно изначально be, и на x86 я могу непосредственно работать с r16 и его половинками. На le мне уже придется обращаться к r8[index ^ 1]. А есть ведь архитектуры, где например нет 16-битных регистров, а обращение к некратному 32 адресу вызывает исключение.
В общем хочется делать всякие бинарные операции без лишних костылей и наиболее прозрачно.

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

Лучше уточните специфику задачи, а то как то странно звучит:

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

Может это действительно так и может нужно вводит в программу что вида

#if defined(__BIG_ENDIAN_BITFIELD)

и писать сразу два варианта кода.

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

Данные должны быть доступны в заданном формате, работать с ними нужно интенсивно.
Собственно мой вопрос как раз о том, как избежать написания нескольких вариантов кода, при этом сильно не усложнив и не утяжелив, возможно ли это.
Допустим я ввел сущность endian со значением 0 или 1, которую буду встраивать в выражения, например для индексации половинок типов. Но есть менее предсказуемые операции, в этом направлении и хочется разузнать.

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

В общем хочется делать всякие бинарные операции без лишних костылей и наиболее прозрачно.

У тебя какое-то странное представление о накладных расходах. Делаешь следующий набор функций:

int is_big_endian(void);
void swap_bytes_16(uint16_t *bytes);
void swap_bytes_32(uint32_t *bytes);
void swap_bytes_64(uint64_t *bytes);

Что они делают - думаю, объяснять не надо. И там где надо, проверяешься систему на эндиан, если результат не совпадает с целевой машиной - меняешь соответствующими функциями байты в переменно или в массиве, как там у тебя.

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

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

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

Пример из пальца:

А реалистичный пример можно?

А есть ведь архитектуры, где например нет 16-битных регистров, а обращение к некратному 32 адресу вызывает исключение.

И что это за архитектура? Вроде что-то подобное было на старых Альфах, но обычно в самом компиляторе Си есть поддержка 8-,16-, и 32-бит целых. Конечно, они должны быть выравнены.

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

>Делаешь следующий набор функций:
плюсую. и дополню:
я однажды сделал так: помимо этих функций объявил функции dummy_{16,32,64}, возвращающие неизмененный аргумент.
и объявил глобальные указатели. и функцию, их инициализирующую.
и больше проблем не знал.

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

>глобальные указатели
указатели на функции, разумеется.

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

>>я однажды сделал так: помимо этих функций объявил функции dummy_{16,32,64}, возвращающие неизмененный аргумент.

Да, если возможность позволяет, так будет еще проще и не надо париться по поводу проверки эндиана.

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

>>>я однажды сделал так: помимо этих функций объявил функции dummy_{16,32,64}, возвращающие неизмененный аргумент.

Да, если возможность позволяет, так будет еще проще и не надо париться по поводу проверки эндиана.

Туплю: а почему в compile-time не проверять эти вещи? Думаете htonl и ко через указатели сделаны?

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

>>Туплю: а почему в compile-time не проверять эти вещи?

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

Думаете htonl и ко через указатели сделаны?

Скорее всего.

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

> Делаешь следующий набор функций:
Всё уже сделано. Дреппера таки доканали :)

man 3 endian

Slavaz ★★★★★
()
Ответ на: комментарий от MuZHiK-2

>Ну а откуда тебе знать, каким будет бинарник?

А с макросами как всегда бардак и отсутствие стандартов?

>А вообще есть системы, которые могут переключать этот режим

o_O Может, там ещё тумблер есть, переключающий биты и триты?

>>>Думаете htonl и ко через указатели сделаны? >Скорее всего.

/usr/include/netinet/in.h:

#   define htonl(x)   __bswap_32 (x)

/usr/include/bits/byteswap.h:

#  define __bswap_32(x)                                                       \
     (__extension__                                                           \
      ({ register unsigned int __v, __x = (x);                                \
         if (__builtin_constant_p (__x))                                      \
           __v = __bswap_constant_32 (__x);                                   \
         else                                                                 \
           __asm__ ("rorw $8, %w0;"                                           \
                    "rorl $16, %0;"                                           \
                    "rorw $8, %w0"                                            \
                    : "=r" (__v)                                              \
                    : "0" (__x)                                               \
                    : "cc");                                                  \
         __v; }))
legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>>А с макросами как всегда бардак и отсутствие стандартов?

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

o_O Может, там ещё тумблер есть, переключающий биты и триты?

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

define htonl(x) __bswap_32 (x)

Разве эти дефайны не привязываются к операционке? Может потеряться портабельность, особенно с разными компиляторами.

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

>Разве эти дефайны не привязываются к операционке?

Ифдефы я, понятное дело, опустил. Там много ещё чего. Если компилер считает, что цель big-endian, то подставляет вместо __bswap_32 заглушку. В рантайме ничего не определяется. Если вы нажали на своём системнеке button of endianess, будьте добры запустить другой бинарник.

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

>>Если вы нажали на своём системнеке button of endianess, будьте добры запустить другой бинарник.

Вообще, эту проблему должна ОС решать. Просто лично я люблю максимально универсальные решения :)

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

>так будет еще проще и не надо париться по поводу проверки эндиана.
париться придется, но только один раз - при инициализации указателей
(так сложилось, что мне пришлось в рантайме определять формат (LE/BE) входного файла)

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