C89: несоответствие со знаком / без знака - PullRequest
5 голосов
/ 14 февраля 2010

Несоответствия со знаком / без знака обязательно плохие?

Вот моя программа:

int main(int argc, char *argv[]) {
    unsigned int i;

    for (i = 1; i < argc; i++) { // signed/unsigned mismatch here

    }
}

argc подписано, i нет. Это проблема?

Ответы [ 4 ]

9 голосов
/ 15 февраля 2010

«несоответствия со знаком / без знака» могут быть плохими. В своем вопросе вы спрашиваете о сравнениях. При сравнении двух значений одного и того же базового типа, но одного со знаком и одного без знака, значение со знаком преобразуется в без знака. Таким образом,

int i = -1;
unsigned int j = 10;

if (i < j)
    printf("1\n");
else
    printf("2\n");

печатает 2, а не 1. Это потому, что в i < j i преобразуется в unsigned int. (unsigned int)-1 равно UINT_MAX, очень большое число. Таким образом, условие оценивается как ложное, и вы попадаете в предложение else.

Для вашего конкретного примера, argc гарантированно будет неотрицательным, поэтому вам не нужно беспокоиться о «несоответствии».

1 голос
/ 15 февраля 2010

Это не плохо. Я бы исправил предупреждения компилятора о несоответствии со знаком / без знака, потому что плохие вещи могут случиться, даже если они маловероятны или невозможны. Когда вам нужно исправить ошибку из-за несоответствия со знаком или без знака, компилятор в основном говорит: «Я сказал вам об этом». Не игнорируйте предупреждение там по причине.

1 голос
/ 15 февраля 2010

Это только косвенная проблема.

Плохие вещи могут случиться, если вы используете целые числа со знаком для битовых операций, таких как &, |, << и >>.
Совершенно разные плохие вещи могут произойти, если вы используете целые числа без знака для арифметики (недостаточное значение, бесконечные циклы при тестировании, если число равно >= 0 и т. Д.)

Из-за этого некоторые компиляторы и инструменты статической проверки будут выдавать предупреждения при смешивании целых чисел со знаком и без знака в любом типе операции (арифметическая или битовая манипуляция).

Хотя это может быть безопасно смешивать их в простых случаях, таких как ваш пример, если вы сделаете это, это означает, что вы не можете использовать эти инструменты статической проверки (или должны отключить эти предупреждения), что может означать, что другие ошибки остаются незамеченными.

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

В вашем примере я бы придерживался int только потому, что проще иметь меньше типов, и в любом случае int будет там, поскольку это тип первого аргумента main().

1 голос
/ 15 февраля 2010

Это не реальная проблема в вашем конкретном случае, но компилятор не может знать, что argc всегда будет иметь значения, которые не вызовут никаких проблем.

...