Продвижение типов данных во время арифметических операций: -1 <(unsinged int) 1 == false - PullRequest
10 голосов
/ 10 октября 2010
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.

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

, тогда вывод будет NOT less than.

Так что очевидно, что когда я заменяю unsigned char на unsigned int:

  • (подписано) -1 преобразуется в unsigned int [происходит прямо противоположное]
  • , поскольку -1 сохраняется как комплимент 2 для 1;битовый шаблон оценивается как 255 (вероятно)
  • , поэтому 255 <1 будет оцениваться как false, а в противном случае будет выполняться. </li>
  • , даже если вместо '-1' подставить int a = -1;тот же результат

Вопросы:

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

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

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

Ответы [ 2 ]

10 голосов
/ 10 октября 2010

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

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

...

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

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

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

  • -1 < (unsigned char) 1

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

  • -1 < (unsigned int) 1

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

1 голос
/ 10 октября 2010

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

ИСО С 6.3.1.1, пункт 2:

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

...