Если вы намереваетесь хранить произвольные двоичные данные, вы должны использовать unsigned char
. Это единственный тип данных, который гарантированно не содержит битов заполнения в стандарте C. Каждый другой тип данных может содержать биты заполнения в своем представлении объекта (то есть тот, который содержит все биты объекта, а не только те, которые определяют значение). Состояние битов заполнения не определено и не используется для хранения значений. Таким образом, если вы читаете, используя char
некоторые двоичные данные, все будет сокращено до диапазона значений символа (путем интерпретации только битов значения), но могут оставаться биты, которые просто игнорируются, но все еще существуют и читаются memcpy
. Очень похоже на заполнение битов в реальных объектах структуры. Тип unsigned char
гарантированно не содержит их. Это следует из 5.2.4.2.1/2
(C99 TC2, n1124 здесь):
Если значение объекта типа char рассматривается как целое число со знаком при использовании в
выражением, значение CHAR_MIN
должно быть таким же, как у SCHAR_MIN
, а
значение CHAR_MAX
должно совпадать со значением SCHAR_MAX
. В противном случае значение
CHAR_MIN
должно быть 0, а значение CHAR_MAX
должно быть таким же, как
UCHAR_MAX
. Значение UCHAR_MAX
должно равняться 2^CHAR_BIT − 1
Из последнего предложения следует, что для любых битов заполнения не осталось места. Если вы используете char
в качестве типа вашего буфера, у вас также возникает проблема переполнения: присваивать любое значение явно одному такому элементу, который находится в диапазоне 8
битов - так что вы можете ожидать, что такое назначение будет в порядке - но не в диапазоне char
, который равен CHAR_MIN
.. CHAR_MAX
, такое преобразование переполняется и вызывает результаты, определенные реализацией, включая повышение сигналов.
Даже если какие-либо проблемы, касающиеся вышеизложенного, вероятно, не будут проявляться в реальных реализациях (это будет очень низкое качество реализации), лучше всего использовать правильный тип с самого начала, а именно unsigned char
.
Однако для строк выбирается тип данных char
, который будет понятен для функций строк и печати. Использование signed char
для этих целей кажется мне неправильным решением.
Для получения дополнительной информации прочитайте this proposal
, в котором содержится исправление для следующей версии Стандарта C, которое, в конечном счете, потребует signed char
также без битов заполнения. Он уже включен в рабочий документ .