n=256;
преобразует целое значение со знаком 256
в uint8_t
, а затем присваивает его n
.Это преобразование определено стандартом для принятия значения по модулю 256, поэтому в результате n
устанавливается на 0
.
Не уверен, где можно найти таблицу, но правила для целых чиселпреобразования производятся в 6.3.1.3:
1 Когда значение с целочисленным типом преобразуется в другой целочисленный тип, отличный от _Bool, если значение может быть представлено новым типом, оно не изменяется.
2 В противном случае, если новый тип является беззнаковым, значение преобразуется путем многократного сложения или вычитания более одного максимального значения, которое может быть представлено в новом типе, до тех пор, пока значение не окажется в диапазоне нового типа.49)
3 В противном случае новый тип подписывается и значение не может быть представлено в нем;либо результат определяется реализацией, либо определяется сигнал реализации
Как указывает AndreyT, это не охватывает то, что происходит, когда во время вычисления возникает значение вне допустимого диапазона, так какв отличие от во время преобразования.Для типов без знака, описанных в разделе 6.2.5 / 9:
Вычисления, включающие операнды без знака, никогда не могут переполниться, поскольку результат, который не может быть представлен результирующим целочисленным типом без знака, уменьшается по модулю на число, которое являетсяна единицу больше наибольшего значения, которое может быть представлено результирующим типом.
Для типов со знаком 3.4.3 / 3 говорит:
ПРИМЕР Пример неопределенного поведенияэто поведение при целочисленном переполнении.
(косвенно, я знаю, но мне лень продолжать искать явное описание, когда это канонический пример неопределенного поведения).
Также обратите внимание, что в C правила целочисленного продвижения довольно хитры.Арифметические операции всегда выполняются над операндами одного и того же типа, поэтому, если ваше выражение включает в себя разные типы, существует список правил, чтобы решить, как выбрать тип, в котором будет выполняться операция. Оба операнда повышаются до этого общего типа.Это всегда, по крайней мере, int, поэтому для маленького типа, такого как uint8_t
, арифметика будет выполнена в int
и преобразована обратно в uint8_t
при присвоении результата.Следовательно, например:
uint8_t x = 100;
uint8_t y = 100;
unsigned int z = x * y;
приводит к 10000, а не к 16, что было бы результатом, если бы z тоже было uint8_t
.
Также допустимо ли использование C99PRI * макросы?Как они названы?
Приемлемо для кого?Я не против, но вы можете проверить, поддерживает ли ваш компилятор их или нет.GCC делает в самой ранней версии, которую я имею, 3.4.4.Они определены в 7.8.1.
Если у вас нет копии стандарта C, используйте это: http://www.open -std.org / jtc1 / sc22 / WG14 / www / docs/n1256.pdf.Это «черновик» стандарта, выпущенный через некоторое время после опубликования стандарта и включающий некоторые исправления.