Как набрать приведение литерала в C - PullRequest
6 голосов
/ 01 сентября 2009

У меня есть небольшая функция выборки:

#define VALUE 0

int test(unsigned char x) {
  if (x>=VALUE)
    return 0;
  else
    return 1;
}

Мой компилятор предупреждает меня, что сравнение (x> = VALUE) истинно во всех случаях, и это правильно, потому что x - это знак без знака, а VALUE определяется со значением 0. Поэтому я изменил свой код на:

if ( ((signed int) x ) >= ((signed int) VALUE ))

Но предупреждение приходит снова. Я протестировал его с тремя версиями GCC (все версии> 4.0, иногда вам нужно включить -Wextra).

В измененном случае у меня есть это явное приведение, и это должно быть сравнение int со знаком. Почему утверждается, что сравнение всегда верно?

Ответы [ 4 ]

12 голосов
/ 01 сентября 2009

Даже с приведенным составом сравнение все еще верно во всех случаях определенного поведения. Компилятор по-прежнему определяет, что (signed int)0 имеет значение 0, и по-прежнему определяет, что (signed int)x) неотрицательно, если ваша программа имеет определенное поведение (приведение от неподписанного к подписанному не определено, если значение находится вне диапазона для подписанного типа) .

Таким образом, компилятор продолжает предупреждать, потому что он продолжает полностью исключать другой случай.

Редактировать : Чтобы отключить предупреждение, напишите свой код как

#define VALUE 0

int test(unsigned char x) {
#if VALUE==0
  return 1;
#else
  return x>=VALUE;
#endif
}
7 голосов
/ 01 сентября 2009

x - это unsigned char, то есть от 0 до 256. Поскольку int больше char, приведение unsigned char к signed int все еще сохраняет исходное значение char s. , Поскольку это значение всегда> = 0, ваше if всегда истинно.

3 голосов
/ 01 сентября 2009

Все значения unsigned char могут отлично сработать в вашем int, поэтому даже с приведением вы никогда не получите отрицательное значение. Нужно привести signed char, однако в этом случае вы должны объявить x как signed в сигнатуре функции. Клиентам нет смысла врать, что вам нужно значение без знака, а на самом деле вам нужно значение со знаком.

1 голос
/ 01 сентября 2009

#define от VALUE до 0 означает, что ваша функция сводится к этому:

int test(unsigned char x) {
  if (x>=0)
    return 0;
  else
    return 1;
}

Так как x всегда передается как unsigned char, то оно всегда будет иметь значение от 0 до 255 включительно, независимо от того, передали ли вы x или 0 в signed int в if заявлении. Поэтому компилятор предупреждает вас, что x всегда будет больше или равно 0 и что предложение else никогда не будет достигнуто.

...