Различные типы данных - подписанные и неподписанные
Я только что выполнил следующий код
main()
{
char a = 0xfb;
unsigned char b = 0xfb;
printf("a=%c,b=%c",a,b);
if(a==b) {
printf("\nSame");
}
else {
printf("\nNot Same");
}
}
Для этого кода я получил ответ как
а =? б =?
Разные
Почему я не получаю Same, и каково значение для a и b?
4 ответа
Есть 2 случая для рассмотрения:
- если
char
тип по умолчанию не подписан, обаa
а такжеb
присваиваются значения251
и программа напечатаетSame
, - если
char
Тип подписан по умолчанию, что, увы, является наиболее распространенным случаем, определениеchar a = 0xfb;
имеет поведение, определяемое реализацией как0xfb
(251
в десятичном), вероятно, вне диапазона дляchar
тип (обычно-128
в127
). Скорее всего значение-5
будет храниться вa
а такжеa == b
оценивает0
поскольку оба аргумента повышены доint
до сравнения, следовательно-5 == 251
будет ложным
Поведение printf("a=%c,b=%c", a, b);
также зависит от системы как символы не ASCII -5
а также 251
может печатать неожиданными способами, если вообще. Обратите внимание, что оба будут печатать так же, как %c
Формат указывает, что аргумент преобразуется в unsigned char
перед печатью. Было бы безопаснее и точнее попробовать printf("a=%d, b=%d\n", a, b);
С помощью gcc или clang вы можете попробовать перекомпилировать вашу программу с -funsigned-char
чтобы увидеть, как поведение будет отличаться.
Линия if (a == b)
... переводит символы в целые числа перед сравнением, поэтому подпись символа влияет на то, как это происходит. Знак без знака 0xFB становится целым числом 251; подписанный символ 0xFB становится целым числом -5. Таким образом, они неравны.
Согласно стандарту C (6.5.9 операторы равенства)
4 Если оба операнда имеют арифметический тип, выполняются обычные арифметические преобразования....
Обычные арифметические преобразования включают целочисленные продвижения.
Из стандарта C (6.3.1.1 Boolean, символы и целые числа)
2 Следующее может использоваться в выражении везде, где могут использоваться int или unsigned int:...
Если int может представлять все значения исходного типа (как ограничено шириной для битового поля), значение преобразуется в int; в противном случае он конвертируется в беззнаковое целое. Они называются целочисленными промоушенами.58) Все остальные типы не меняются при целочисленных акциях.
Так что в этом выражении равенства
a == b
оба операнда преобразуются в тип int
, Операнд со знаком (при условии, что тип char
ведет себя как тип signed char
) преобразуется в тип int
посредством распространения знакового бита.
В результате операнды имеют разные значения из-за разницы в двоичном представлении.
Если тип char
ведет себя как тип unsigned char
(например, установив соответствующую опцию компилятора), тогда, очевидно, операнды будут равны.
char
магазины от -128 до 127 и unsigned char
магазины от 0 до 255. и 0xfb
представляет 251 в десятичном виде, который находится за пределами char a
,