# V104. Implicit type conversion to memsize type in an arithmetic expression.

Анализатор обнаружил потенциально возможную ошибку внутри арифметического выражения, связанную с неявным приведением к типу memsize. Ошибка переполнения может быть связана с изменением допустимого интервала значений переменных, входящих в выражение.

Первый пример.

Некорректные выражения сравнения. Рассмотрим код:

    size_t n;
    unsigned i;
    // Infinite loop (n > UINT_MAX).
    for (i = 0; i != n; ++i) { ... }

В примере показана ошибка, связанная с неявным приведением типа 'unsigned' к типу 'size_t' при выполнении операции сравнения.

На 64-битной платформе у вас может появиться возможность обрабатывать больший объем данных, и значение переменной 'n' может превысить число 'UINT_MAX' (4 Гб). В результате, условие "i != n" всегда будет истинно, что приведет к вечному циклу.

Пример исправленного кода:

    size_t n;
    size_t i;
    for (i = 0; i != n; ++i) { ... }

Второй пример.

    char *begin, *end;
    int bufLen, bufCount;
    ...
    ptrdiff_t diff = begin - end + bufLen * bufCount;

Неявное приведение типа 'int' к типу 'ptrdiff_t' зачастую служит признаком ошибки. Следует обратить внимание, что приведение происходит не при выполнении оператора "=" (так как выражение "begin - end + bufLen * bufCount" имеет тип 'ptrdiff_t'), а внутри этого выражения. Подвыражение "begin - end" согласно правилам языка С++ имеет тип 'ptrdiff_t', а правая "bufLen * bufCount" тип 'int'. При переходе на 64-битную платформу программа может начать обрабатывать больший объем данных, в результате чего может произойти переполнение при вычислении подвыражения "bufLen * bufCount".

Следует изменить тип переменных 'bufLen' и 'bufCount' на memsize тип или использовать явное приведение типа, как показано на примере:

    char *begin, *end;
    int bufLen, bufCount;
    ...
    ptrdiff_t diff = begin - end +
      ptrdiff_t(bufLen) * ptrdiff_t(bufCount);

Отметим, что неявное приведение к типу memsize внутри выражений не всегда является ошибочным. Рассмотрим следующую ситуацию:

    size_t value;
    char c1, c2;
    size_t result = value + c1 * c2;

Анализатор не выдает сообщения, хотя здесь происходит приведение типа 'int' к 'size_t', так как при вычислении подвыражения "c1 * c2" переполнения произойти не может.

Если вы подозреваете в программе наличие ошибок, связанных с некорректным явным приведением типов в выражениях, то Вы можете воспользоваться правилом V201. Пример ситуации, при которой явное приведение типа к 'size_t' скрывает ошибку, представлен ниже:

    int i;
    size_t st;
    ...
    st = size_t(i * i * i) * st;

Дополнительные материалы по данной теме:

- 64-битные уроки. Урок 17. Паттерн 9. Смешанная арифметика.