Целочисленная точность превышена

Операция с помощью целочисленного размера вместо точности может вызвать неопределенное поведение

Описание

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

Риск

Используя размер целого числа в операции на целочисленной точности может привести к целочисленному переполнению, повториться, или неожиданные результаты. Например, беззнаковое целое может храниться в памяти в 64 битах, но использует только 48 битов, чтобы представлять его значение. Операция сдвига влево на 56 битов на этом целом числе является неопределенным поведением.

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

Фиксация

Не используйте размер целого числа вместо его точности. Чтобы определить целочисленную точность, реализуйте стандартную программу вычисления точности или используйте встроенную функцию, такую как __builtin_popcount().

Примеры

развернуть все

#include <limits.h>

unsigned int func(unsigned int exp)
{
    if (exp >= sizeof(unsigned int) * CHAR_BIT) {
        /* Handle error */
    }
    return 1U << exp;
}

В этом примере функция использует операцию сдвига влево, чтобы возвратить значение 2 возведенных в степень из exp. Операция переключает биты 1U положениями exp налево. Оператор if гарантирует, что операция не переключает биты многими положениями exp, больше, чем размер unsigned int. Однако, если unsigned int содержит дополнительные биты, значение, возвращенное sizeof(), больше, чем точность unsigned int. В результате некоторые значения exp могут быть слишком большими, и операция сдвига может быть неопределенным поведением.

Исправление — функция реализации, чтобы вычислить точность unsigned int

Одно возможное исправление должно реализовать функциональный popcount(), который вычисляет точность unsigned int путем подсчета количества битов набора.

#include <stddef.h>
#include <stdint.h>
#include <limits.h>

size_t popcount(uintmax_t);
#define PRECISION(umax_value) popcount(umax_value)


unsigned int func(unsigned int exp)
{
    if (exp >= PRECISION(UINT_MAX)) {
        /* Handle error */
    }
    return 1 << exp;
}




size_t popcount(uintmax_t num)
{
    size_t precision = 0;
    while (num != 0) {
        if (num % 2 == 1) {
            precision++;
        }
        num >>= 1;
    }
    return precision;
} 

Информация о результате

Группа: числовой
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: INT_PRECISION_EXCEEDED
Влияние: низко
ID CWE: 190

Введенный в R2018b