Следует ли вам всегда использовать int для чисел в C, даже если они неотрицательны? - PullRequest
46 голосов
/ 15 июля 2010

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

void CreateRequestHeader( unsigned bitsAvailable, unsigned mandatoryDataSize, 
    unsigned optionalDataSize )
{
    If ( bitsAvailable – mandatoryDataSize >= optionalDataSize ) {
        // Optional data fits, so add it to the header.
    }

    // BUG! The above includes the optional part even if
    // mandatoryDataSize > bitsAvailable.
}

Должен ли я начать использовать int вместо unsigned int для чисел, даже если они не могут бытьотрицательный?

Ответы [ 16 ]

2 голосов
/ 15 июля 2010

Ситуация, когда (bitsAvailable – mandatoryDataSize) дает «неожиданный» результат, когда типы не подписаны, а bitsAvailable < mandatoryDataSize - причина, по которой иногда используются подписанные типы, даже если ожидается, что данные никогда не будут отрицательными.

Я думаю, что нет строгого и быстрого правила - я обычно «по умолчанию» использую неподписанные типы для данных, у которых нет причин быть отрицательными, но тогда вы должны принять меры, чтобы арифметическая упаковка не выявила ошибок. *

Опять же, если вы используете подписанные типы, вам все равно придется иногда учитывать переполнение:

MAX_INT + 1

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

1 голос
/ 16 июля 2010

Если существует вероятность переполнения, присвойте значения следующему наивысшему типу данных во время вычисления, например:

void CreateRequestHeader( unsigned int bitsAvailable, unsigned int mandatoryDataSize, unsigned int optionalDataSize ) 
{ 
    signed __int64 available = bitsAvailable;
    signed __int64 mandatory = mandatoryDataSize;
    signed __int64 optional = optionalDataSize;

    if ( (mandatory + optional) <= available ) { 
        // Optional data fits, so add it to the header. 
    } 
} 

В противном случае, просто проверьте значения по отдельности вместо расчета:

void CreateRequestHeader( unsigned int bitsAvailable, unsigned int mandatoryDataSize, unsigned int optionalDataSize ) 
{ 
    if ( bitsAvailable < mandatoryDataSize ) { 
        return;
    } 
    bitsAvailable -= mandatoryDataSize;

    if ( bitsAvailable < optionalDataSize ) { 
        return;
    } 
    bitsAvailable -= optionalDataSize;

    // Optional data fits, so add it to the header. 
} 
0 голосов
/ 16 июля 2010

Предположим, вам нужно сосчитать от 1 до 50000. Это можно сделать с помощью двухбайтового целого числа без знака, но не с помощью двухбайтового целого числа со знаком (если пробел так важен).

0 голосов
/ 16 июля 2010

Если ваши числа должны никогда не быть меньше нуля, но иметь шанс быть <0, во что бы то ни стало используйте целые числа со знаком и посыпьте утверждения или другие проверки во время выполнения.Если вы на самом деле работаете с 32-битными (или 64, или 16, в зависимости от вашей целевой архитектуры) значениями, где старший значащий бит означает что-то отличное от «-», вы должны использовать только переменные без знака для их хранения.Целочисленные переполнения легче обнаружить, когда число, которое всегда должно быть положительным, очень отрицательно, чем когда оно равно нулю, поэтому, если вам не нужен этот бит, используйте со знаком. </p>

0 голосов
/ 15 июля 2010

Я не знаю, возможно ли это в c, но в этом случае я просто приведу XY к int.

0 голосов
/ 15 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...