Подтвердить что ты не робот

C/С++ использование int или unsigned int

Во многих примерах кода, исходном коде, библиотеках и т.д. Я вижу использование int, когда, насколько я вижу, unsigned int имеет смысл.

Одно место, которое я вижу, это много for циклов. Пример ниже:

for(int i = 0; i < length; i++)
{
    // Do Stuff
}

Почему бы вам не использовать int а не unsigned int? Это просто лень - люди не могут беспокоиться о наборе unsigned?

4b9b3361

Ответ 1

Использование unsigned может привести к ошибкам программирования, которые трудно обнаружить, и обычно лучше использовать подписанный int, чтобы избежать их. Например, если вы решите повторить назад, а не вперед, и напишите это:

for (unsigned i = 5; i >= 0; i--) {
    printf("%d\n", i);
}

Другое могло бы быть, если вы выполните некоторую математику внутри цикла:

for (unsigned i = 0; i < 10; i++) {
    for (unsigned j = 0; j < 10; j++) {
        if (i - j >= 4) printf("%d %d\n", i, j);
    }
}

Использование unsigned вводит потенциал для этих видов ошибок, и на самом деле нет никакого роста.

Ответ 2

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

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

IMHO, утверждение, что безопаснее использовать "int", чем "unsigned int", является просто неправильным и плохой практикой программирования.

Если вы использовали Ada или Pascal, вы привыкли бы использовать более безопасную практику указания конкретных диапазонов значений (например, целое число, которое может быть только 1, 2, 3, 4, 5).

Ответ 3

Если length также int, то вы должны использовать один и тот же целочисленный тип, в противном случае происходят странные вещи, когда вы смешиваете подписанные и неподписанные типы в инструкции сравнения. Большинство компиляторов выдаст вам предупреждение.

Вы можете задать вопрос: зачем подписываться length? Ну, это, вероятно, историческое.

Кроме того, если вы решили перевернуть цикл, то есть

for(int i=length-1;i>=0 ;i--)
{
   // do stuff
}

логика прерывается, если вы используете unsigned ints.

Ответ 4

Я предпочел быть максимально явным во время программирования. То есть, если я намерен использовать переменную, значение которой всегда положительно, то используется unsigned. Многие здесь упоминают "трудно обнаружить ошибки", но мало примеров. Рассмотрим следующий пример защитника для использования unsigned, в отличие от большинства сообщений здесь:

enum num_things {
    THINGA = 0,
    THINGB,
    THINGC,
    NUM_THINGS
};

int unsafe_function(int thing_ID){
    if(thing_ID >= NUM_THINGS)
        return -1;

    ...
}

int safe_function(unsigned int thing_ID){
    if(thing_ID >= NUM_THINGS)
        return -1;

    ...
}

int other_safe_function(int thing_ID){
    if((thing_ID >=0 ) && (thing_ID >= NUM_THINGS))
        return -1;

    ...
}

/* Error not caught */
unsafe_function(-1);

/* Error is caught */
safe_function((unsigned int)-1);

В приведенном выше примере, что произойдет, если отрицательное значение передается как thing_ID? В первом случае вы обнаружите, что отрицательное значение не больше или равно NUM_THINGS, и поэтому функция будет продолжать выполнение.

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

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

Ответ 5

Я думаю, что самая важная причина в том, что если вы выберете unsigned int, вы можете получить некоторые логические ошибки. На самом деле вам часто не нужен диапазон unsigned int, использование int безопаснее.

Ответ 6

Я использую unsigned int только тогда, когда длина больше максимального значения int. Использование unsigned int может вводить трудноопределяемые ошибки, особенно если длина переменной.

Ответ 7

этот крошечный код связан с usecase, если вы вызываете некоторый векторный элемент, тогда прототип является int, но в c++ есть много современных способов сделать это. for (const auto & v: vec) {} или итераторы, при некотором исчислении, если нет вычитания/достижения отрицательного числа, которое вы можете и должны использовать без знака (лучше объясняет диапазон ожидаемых значений), иногда так много опубликованных примеров показывает, нужна интуиция, но правда в том, что все дело об использовании и ситуации, ни одно строгое правило не применяется ко всем обычаям, и было бы неразумно заставлять их...