Различные типы данных - подписанные и неподписанные

Я только что выполнил следующий код

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,

Другие вопросы по тегам