Когда uint8_t ≠ без знака char?

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

В какой системе можно < <22 > быть юридически определенным как тип, отличный от unsigned char?

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

Ответ 1

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

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

Ответ 2

О какой системе может быть 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, без знака char или подписанный 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.

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

Ответ 3

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