Что: 4a1cde747924fa08548d1092f1c5e366cf2ce877
Когда: 2022-10-16 13:17:41+03:00
Темы: c hate
Про endianness работу в Си https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html В b45f896af5ca60802cbae0a00d8223857a771eba я давал ссылки на тему про endianness конвертацию в Си. Но на днях на работе мне прислали вопрос уверен ли я что с endianness нет проблем в таком куске кода тривиальном: size_t len = (size_t)(data[2] << 8) | data[3]; Отвечаю что возможно я какой-то очередной подвох в Си не знаю, но что в нём не так? Мне кидают информацией об endian.h и be16toh(). Отвечаю что в курсе их существования, но: * конкретно у be16toh менее удобный API (указатели все эти) * be16dec, который удобен для использования, не факт что есть в glibc, как например в нём, как оказалось, не было be64dec * endian.h include не портабельный: в BSD системах это sys/endian.h * плюсом будет только отсутствие *нескольких* арифметических операций при запуске на BE-архитектуре. Если бы речь шла про миллионы пакетов в секунду, то возможно можно было бы начать задумываться об этом, но речь про один пакет за нескольких секунд (это просто парсинг его размера) Коллега никакого ответа на это так и не дал, только повторив что в одном случае порядок меняется, а в другом нет. Но до сих пор не знаю к чему этот ответ. Можно или писать чуть-чуть более эффективный код, который, в зависимости от endianness платформы, будет тасовать байты или будет использовать их as-is без преобразований. Или писать код независимый от endianness вообще, в котором несколько тривиальных инструкций выполняются всегда, пускай даже когда это и не надо (совпадающий endianness платформы и данных). Позже вспомнил про статью Роба Пайка, в которой он тоже считает всё это фигнёй. Мол, если в коде есть #ifdef BIG_ENDIAN, то это не порядок. Вместо того, чтобы написать: i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); такие люди будут писать что-то типа: i = *((int*)data); #ifdef BIG_ENDIAN i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0); #endif или, для случая с моим 16-бит кодом: #include#ifdef __FreeBSD__ || ... #include #elif __linux__ #include #endif [...] uint16_t *lenp = (uint16_t *)(&data[2]); size_t len = (be16toh(*rtcplen); Что, очевидно, гораздо больше года. Плюс не везде возможно целые числа адресовать по любому адресу (выравнивания). In fact, byte-swapping is the surest indicator the programmer doesn't understand how byte order works. Why do people make the byte order mistake so often? I think it's because they've seen a lot of bad code that has convinced them byte order matters. Plan 9 вообще без единого, как говорит Пайк, platform-specific #ifdef-а был написан.
Сгенерирован: SGBlog 0.34.0
text/gemini
This content has been proxied by September (ba2dc).