Предупреждение: эта десятичная константа не имеет знака только в ISO C90 - PullRequest
17 голосов
/ 30 марта 2012

Кусок кода:

long rangeVar = 0;
rangeVar = atol(p_value);

if (rangeVar >= -2147483648 && rangeVar <= 2147483647)

При компиляции я получаю:

предупреждение: эта десятичная константа без знака только в ISO C90

Заранее спасибо

Ответы [ 3 ]

13 голосов
/ 03 января 2014

Правила для типов десятичных целочисленных констант изменились между выпусками стандарта ISO С. 1990 и 1999 гг.

В версии 1990 года тип нефиксированной десятичной целочисленной константы является первым из int, long int или unsigned long int, в котором может быть представлено ее значение. (C90 не имел типа long long или unsigned long long).

В версиях 1999 и 2011 годов его типом является один из int, long int, long long int; это никогда не бывает без знака.

Тип конкретной константы (такой как 2147483648) будет варьироваться в зависимости от диапазонов целочисленных типов для компилятора, который вы используете. Если тип вашего компилятора long равен 32 битам, то 2147483648 будет иметь тип unsigned long, если ваш компилятор использует правила C90, или тип long long, если он использует правила C11 (long long гарантированно будет не менее 64 бит). Компилятор предупреждает вас об этом.

Вы можете добавить суффиксы, чтобы указать тип константы, но суффикса для простой подписи int нет. Вы можете добавить U для unsigned int, L для long, UL для длинных без знака и т. Д.

Важно помнить, что -2147483648 является , а не целочисленной константой; скорее 2147483648 само по себе является целочисленной константой, а -2147483648 является выражением, которое применяет унарный оператор минус к этой константе. Согласно правилам C90, если константа имеет тип unsigned long, это беззнаковый унарный минус, который по правилам арифметики без знака дает значение 2147483648. В соответствии с правилами C99 или C11 2147483648, скорее всего, относится к типу (со знаком) long long, а его отрицание приводит к -2147483648, также типа long long.

Иногда вы увидите код, который использует (-2147483647 - 1), чтобы избежать этой проблемы; для 32-битного int, 2147483647 имеет тип int, а результат выражения возвращает ожидаемое значение int без переполнения.

Конечно, если ваш компилятор имеет разные размеры для целочисленных типов, это может стать еще более сложным.

10 голосов
/ 30 марта 2012

Да, это одна вещь, которая не очень хорошо обрабатывается компилятором.Проблема заключается в том, что во время компиляции это число 2147483648, которое отрицается, а 2147483648 выходит за пределы диапазона для целого числа.Даже если -2147483648 не будет!

В любом случае, чтобы избавиться от предупреждения, вы можете превратить константу в 64-битное число, написав -2147483648LL.
Хотя это излишне, поэтому предпочтительнееспособ будет использовать INT_MIN для константы.Но тогда вам нужно будет включить <limits.h>.

1 голос
/ 03 января 2014

Да, 2147483648 не является действительным положительным значением, потому что оно выходит за допустимые пределы для дополнения 2 на 32-битных машинах, поэтому они просто пытаются предупредить вас, что на некоторых компиляторах это может не дать вам желаемого значения, если они не относитесь к отрицанию по-современному.

Мне кажется, стоит добавить еще один ответ, чтобы указать, что если вы посмотрите на большинство реализаций limit.h, вы увидите, что они обойдут это с помощью (-2147483647 - 1).

...