Когда uint8 t ≠ неподписанный символ?


Согласно C и C++, CHAR_BIT >= 8.
Но всякий раз, когда CHAR_BIT > 8, uint8_t даже не может быть представлено в виде 8 бит.
Он должен быть больше, потому что CHAR_BIT - это минимальное число битов для любого типа данных в системе.

, на какую систему может uint8_t быть юридически определено, чтобы быть иного типа, чем unsigned char?

(Если ответ отличается для C и C++ , то я хотел бы знать и то, и другое.)

3 54

3 ответа:

Если он существует, то uint8_t всегда должен иметь ту же ширину, что и unsigned char. Однако это не обязательно должен быть один и тот же тип; это может быть отдельный расширенный целочисленный тип. Он также не обязательно должен иметь то же представление, что и unsigned char; например, биты могут интерпретироваться в обратном порядке. Это глупый пример, но он имеет больше смысла для int8_t, где signed char может быть дополнением единиц или знаком-величиной, в то время как int8_t требуется, чтобы быть дополнением двоек.

Еще одно "преимущество" использования не-char расширенный целочисленный тип для uint8_t даже в "нормальных" системах-это правила сглаживания C. Символьные типы могут псевдонимировать все, что угодно, что мешает компилятору сильно оптимизировать функции, которые используют как указатели символов, так и указатели на другие типы, если ключевое слово restrict не было применено хорошо. Однако, даже если uint8_t имеет точно такой же размер и представление, как unsigned char, если реализация сделала его отдельным, несимвольным типом, правила псевдонимирования не будут применяться к нему, и компилятор можно было бы предположить, что объекты типов uint8_t и int, например, никогда не могут быть псевдонимами.

О какой системе uint8_t можно юридически определить как тип, отличный от unsigned char?

Таким образом, uint8_t может быть юридически определено только в системах, где CHAR_BIT равно 8. Это адресуемый блок с ровно 8 битами значения и без бит заполнения.

Подробно, CHAR_BIT определяет ширину наименьших адресуемых единиц, и uint8_t не может иметь бит заполнения; он может существовать только тогда, когда наименьшая адресуемая единица имеет ровно 8 бит в ширину. Обеспечение CHAR_BIT равно 8, uint8_t может быть определяется определением типа для любого 8-битного целочисленного типа без знака, не имеющего битов заполнения.


Вот что такое стандартный проект C11 (n1570.pdf) говорит:

5.2.4.2.1 размеры целых типов 1 приведенные ниже значения заменяются постоянными выражениями, пригодными для использования в #if директивы предварительной обработки. ... Их реализация-определенные значения должны быть равны или больше по величине (абсолютной величине) к показанным, с тем же знак.

-- number of bits for smallest object that is not a bit-field (byte)
   CHAR_BIT                                            8
Таким образом, самые маленькие объекты должны содержать ровно биты CHAR_BIT.

6.5.3.4 операторы sizeof и _Alignof

...

4 Когда sizeof применяется к операнду, имеющему тип char, unsigned char или подписано чар (или квалифицированного версия оного) результат 1. ...

Таким образом, это (некоторые из) наименьших адресуемых единиц. Очевидно, что int8_t и uint8_t также могут быть рассмотрены наименьшие адресуемые единицы, если они существуют.

7.20.1.1 целочисленные типы точной ширины

1 имя typedef intN_t обозначает знаковый целочисленный тип с шириной N, никаких бит заполнения и представление дополнения двойки. Таким образом, int8_t обозначает такой знаковый целочисленный тип с шириной ровно 8 биты.

2 имя typedef uintN_t обозначает беззнаковый целочисленный тип с ширина N и отсутствие битов прокладки. Таким образом, uint24_t обозначает такое неподписанный целочисленный тип с шириной ровно 24 бита.

3 Эти типы являются необязательными. однако, если реализация обеспечивает целочисленные типы с шириной 8, 16, 32 или 64 бита, без заполнения битов, и (для подписанных типов), которые имеют дополнение двойки представление, оно должно определять соответствующие имена typedef.

Акцент на "эти типы необязательны " - мой. Я надеюсь, что это было полезно :)

Возможность, о которой до сих пор никто не упоминал: если CHAR_BIT==8 и unqualified char является unsigned, что есть в некоторых ABIs, то uint8_t может быть typedef для char вместо unsigned char. Это имеет значение, по крайней мере, в той мере, в какой это влияет на выбор перегрузки (и его злой двойник, искажение имени), Т. е. если бы вы имели оба foo(char) и foo(unsigned char) в области видимости, вызов foo с аргументом типа uint8_t предпочел бы foo(char) в такой системе.