[О блоге] [наверх] [пред] [2021-12-17 16:56:16+03:00] [153271e2a5ebe0450329c630e19ab92022d9966f]

Байты в Си

https://lists.suckless.org/hackers/2112/18050.html
https://gist.github.com/jibsen/da6be27cde4d526ee564
https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66110
https://github.com/RIOT-OS/RIOT/issues/5497
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2653.htm
Когда начинал писать на Си, то uint8_t показался корректным и правильным
типом данных для представления всяких байтовых последовательностей. Ведь
Си явно не говорит что char вообще то равен байту или 8-ми битам. Как и
автору libgrapheme suckless библиотеки. Но тут начались обсуждения в
рассылке и он изменил всё на char.

Начал изучать вопрос. Пришёл к тому что надо использовать unsigned char
или char (если не думать по будущие стандарты Си), проверяя на всякий
пожарный что оно равно 8-ми битам. Проблема с uint8_t в том, что
безопасно делать алиасы, когда на один и тот же участок памяти ссылаются
несколько переменных, можно когда или типы совместимы или алиасом
является character тип. uint8_t не character тип, поэтому не может быть
алиасом. Поэтому он не должен дружить с -fstrict-aliasing и может мешать
оптимизациям. На практике это работает только потому что GCC/Clang
делают typedef unsigned char uint8_t.

Дальше задался вопросом про signed/unsigned char. Проблем с конвертацией
между этими двумя типами не будет если используется дополнительный код
(two's complement). C99 не диктует что должно быть именно такое
кодирование, но будущий C23 диктует. POSIX диктует и two's complement и
8-бит размер. По этому, в общем то, на POSIX (signed) char можно
безопасно использовать. Более того, в UTF-8 строки в C11 исходном коде
интерпретируются как char *.

Итого, для работы с байтами, кроме void *:
* uint8_t * -- некорректно
* unsigned char * -- всегда корректно, если UCHAR_MAX==255
* char * -- всегда корректно в POSIX

    [оставить комментарий]