Что: 153271e2a5ebe0450329c630e19ab92022d9966f
Когда: 2021-12-17 16:56:16+03:00
Темы: c
Байты в Си 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 *:
Сгенерирован: SGBlog 0.34.0