Одна проблема с типами C99 заключается в том, что, хотя их размеры определяются независимо от платформы, их поведение не определяется.Например, учитывая uint16_t a=3,b=4,c=5; int x= (a > b-c)
, для некоторых реализаций потребуется 1 (так как 3> -1), а для других потребуется 0 (так как 3u <65535u).Во многих случаях можно обойти такие ограничения, явно скрыв результаты операций, а во многих случаях написание кода, например, <code>(a > (uint16_t)(b-c)), (a > ((int)b-c)
или (a > ((int32_t)b-c)
[в зависимости от того, что на самом деле требуется вычислить]сделайте намерение более ясным.
С другой стороны, иногда целочисленные продвижения могут проявляться странным образом.Принимая решение о том, следует ли использовать короткие типы без знака как int со знаком или без знака, авторы C89 отметили, что в большинстве текущих реализаций арифметика со знаком и без знака будет вести себя идентично вне нескольких конкретных контекстов, даже в случаях, выходящих за рамкидиапазон 0..INT_MAX , но некоторые реализации стремятся использовать тот факт, что Стандарт на самом деле не требует этого.Может показаться, что что-то вроде:
unsigned mulMod65535(uint16_t x, uint16_t y) { return (x*y) & 0xFFFF; }
не должно иметь каких-либо побочных эффектов, но если gcc знает, что, например, y == 65535, он будет использовать это для распространения того факта, что x "не может"больше, чем 32768. Интересно, что существующие версии gcc, по-видимому, воздерживаются от такого предположения, если функция вернула uint16_t
, но я не знаю ничего, что обещало бы, что будущие версии не будут более агрессивными.