Продвижение типа данных при арифметических операциях: -1

main()  {   
  if ( -1 < (unsigned char) 1 )
    printf("less than");
  else        
    printf("NOT less than");
} 

печать less than. Так, (unsigned char) 1 превращается в (signed char) 1 и затем: (signed) -1 < (signed) 1, таким образом, выводится less than.

но если я изменю вышеуказанный код to if ( (-1 < (unsigned int) 1 )

затем выводится NOT less than.

поэтому очевидно, что когда я меняю unsigned char на unsigned int:

  • (signed) -1 преобразуется в unsigned int [происходит прямо противоположное]
  • С -1 хранятся в 2 комплимент 1; битовый шаблон оценивается как 255 (вероятно)
  • таким образом, 255
  • даже если вы замените int a = -1; вместо " -1 " тот же результат

вопросы:

  1. во время подписанной и неподписанной арифметики...как убедиться, что signed будет преобразован в unsigned или наоборот.

  2. почему преобразование отличается для арифметики между unsigned char и char: по-видимому, unsigned преобразуется в signed и unsigned int и int: по-видимому, signed преобразуется в unsigned

PS: Я знаю, что это не зависит от компилятора..поэтому не говорите, что это так.

2 ответов


правила таковы:

6.3.1.8 обычные арифметические преобразования

...

в противном случае целочисленные промо-акции выполняются для обоих операндов. Затем к продвигаемым операндам применяются следующие правила:

  1. если оба операнда имеют один и тот же тип, дальнейшее преобразование не требуется.
  2. в противном случае, если оба операнда имеют целочисленные типы со знаком или оба имеют целочисленные типы без знака, операнд с типом преобразования меньшего целого ранга преобразуется в тип операнда с большим рангом.
  3. в противном случае, если операнд с целочисленным типом без знака имеет ранг, больший или равный рангу типа другого операнда, то операнд со знаком целочисленного типа преобразуется в тип операнда с целочисленным типом без знака.
  4. в противном случае, если тип операнда со знаком, целочисленный тип С может представлять все значения тип операнда с беззнаковый целочисленный тип, затем операнда с беззнаковый целочисленный тип преобразуется к типу операнда с типом integer.
  5. в противном случае оба операнда преобразуются в целочисленный тип без знака, соответствующий типу операнда с целочисленным типом со знаком.

затем правила работают следующим образом:

  • -1 < (unsigned char) 1

сначала оба операнда преобразуются в ints (поскольку int может представлять все значения unsigned char). Затем производится сравнение этих типах. Затем используется правило 1. Сравнение успешно.

  • -1 < (unsigned int) 1

int не может представлять все значения unsigned int, поэтому используется правило 3, и целое число со знаком преобразуется в целое число без знака (UINT_MAX - 1). Сравнение теперь проваливается.


Это связано с целое число акций. Оба аргумента могут быть представлены как int, поэтому они преобразуются в int.

ISO C 6.3.1.1, пункт 2:

Если int может представить все значения исходного типа, значение преобразуется к типу int; в противном случае он преобразуется в unsigned int. Они называются целочисленными специальные акции.48) Все остальные типы являются неизменными целыми акциями.