Может ли uint8_t быть несимвольным?
В этом ответе и прилагаемых комментариях Павел Минаев делает следующий аргумент, что в C, единственными типами, для которых uint8_t
может быть typedef'd, являются char
и unsigned char
. Я смотрю этот проект стандарта C.
- Наличие
uint8_t
подразумевает наличие соответствующего типа int8_t
(7.18.1p1).
-
int8_t
имеет ширину 8 бит и не имеет битов заполнения (7.18.1.1p1).
- Соответствующие типы имеют одинаковую ширину (6.2.5p6), поэтому
uint8_t
также имеет ширину 8 бит.
-
unsigned char
имеет ширину CHAR_BIT
(5.2.4.2.1p2 и 6.2.6.1p3).
-
CHAR_BIT
не менее 8 (5.2.4.2.1p1).
-
CHAR_BIT
не более 8, потому что либо uint8_t
есть unsigned char
, либо это не unsigned char
, тип небитового поля, ширина которого кратно CHAR_BIT
(6.2.6.1p4).
Основываясь на этом аргументе, я согласен с тем, что если uint8_t
существует, то и он, и unsigned char
имеют одинаковые представления: 8 битов значения и 0 бит заполнения. Это, похоже, не заставляет их быть одного типа (например, 6.2.5p14).
Допустимо ли, что uint8_t
является typedef'd для расширенного целочисленного типа без знака (6.2.5p6) с тем же представлением, что и unsigned char
? Конечно, это должно быть typedef'd (7.18.1.1p2), и он не может быть любым стандартным беззнаковым целочисленным типом, отличным от unsigned char
(или char
, если он окажется без знака). Этот гипотетический расширенный тип не был бы символьным типом (6.2.5p15) и, следовательно, не мог бы претендовать на доступ к объекту несовместимого типа (6.5p7), который нападает на меня как на причину, по которой автор компилятора захочет сделать такую вещь.
Ответы
Ответ 1
Если uint8_t
существует, требование отсутствия заполнения означает, что CHAR_BIT
равно 8. Однако нет основополагающей причины, почему я могу определить, почему uint8_t
не может быть определен с расширенным целым типом. Более того, нет никаких гарантий, что представления одинаковы; например, биты могут интерпретироваться в обратном порядке.
Хотя это кажется глупым и необычным для uint8_t
, это может иметь большой смысл для int8_t
. Если машина изначально использует дополнение или знак/величину, то signed char
не подходит для int8_t
. Тем не менее, он может использовать расширенный целочисленный тип со знаком, который эмулирует два дополнения для предоставления int8_t
.
Ответ 2
В 6.3.1.1 (1) (черновика N1570 стандарта C11) мы можем читать
Ранг любого стандартного целочисленного типа должен быть больше ранга любого расширенного целочисленного типа с той же шириной.
Таким образом, стандарт явно допускает наличие расширенных целочисленных типов той же ширины, что и стандартный целочисленный тип.
В стандарте нет ничего запрещающего
typedef implementation_defined_extended_8_bit-unsigned_integer_type uint8_t;
если этот расширенный целочисленный тип соответствует спецификациям для uint8_t
(без битов заполнения, ширина 8 бит), насколько я могу видеть.
Так что да, если реализация предоставляет такой расширенный целочисленный тип, uint8_t
может быть typedef'ed к этому.
Ответ 3
uint8_t
может существовать и быть отличным типом от unsigned char
.
Одним из существенных последствий этого является разрешение перегрузки; это зависит от платформы:
uint8_t by = 0;
std::cout << by;
использует
-
operator<<(ostream, char)
-
operator<<(ostream, unsigned char)
или
-
operator<<(ostream, int)
Ответ 4
int8_t и uint8_t отличаются только ПРЕДСТАВЛЕНИЕМ, а не содержимым (битами). int8_t использует более низкие 7 бит для данных, а 8-й бит должен представлять "знак" (положительный или отрицательный). Следовательно, диапазон int8_t составляет от -128 до +127 (0 считается положительным).
uint8_t также имеет ширину 8 бит, НО данные, содержащиеся в нем, ВСЕГДА положительны. Следовательно, диапазон uint8_t составляет от 0 до 255.
Учитывая этот факт, char имеет ширину 8 бит. unsigned char также будет иметь ширину 8 бит, но без знака. Точно так же короткие и неподписанные короткие и 16 бит в ширину.
ЕСЛИ, однако, "unsigned int
" будет иметь ширину 8 бит, тогда.. поскольку C не слишком натурный, это разрешено. И почему автор компилятора допускает такую вещь? ЧИТАЕМОСТЬ!