Нужно ли приводить результат strtol к int?

Следующий код не выдает предупреждение с g++ 4.1.1 и -Wall,

int octalStrToInt(const std::string& s)
{    
    return strtol(s.c_str(), 0, 8);
}

Я ожидал предупреждения, потому что strtol возвращает long int но моя функция только возвращает простую int, Могут ли другие компиляторы выдавать предупреждение здесь? Должен ли я привести приведенное значение к int в этом случае в качестве хорошей практики?

5 ответов

Решение

Вам может понадобиться флаг -Wconversion, чтобы включить эти предупреждения. Тем не менее, он не будет предупреждать о long -> int, поскольку они имеют одинаковый размер с GCC (значение не изменится из-за преобразования). Но это будет, если вы конвертируете, например, long -> short

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

Лучший подход это:

long x = strtol(...); assert(x <= INT_MAX); return (int)x;

Тебе нужно limits.h а также assert.h

Если у вас нет доступа к boost::numeric_castВы можете написать простую имитацию:

template <typename T, typename S>
T range_check(const S &s) {
    assert(s <= std::numeric_limits<T>::max());
    assert(s >= std::numeric_limits<T>::min());
    return static_cast<T>(s); // explicit conversion, no warnings.
}

return range_check<int>(strtol(some_value,0,8));

На самом деле это немного обманывает, поскольку он не работает для типов назначения с плавающей запятой. min() не то же самое для них, как для целочисленных типов, вы должны проверить +/- max(), Упражнение для читателя.

Используете ли вы assert или какую-либо другую обработку ошибок, зависит от того, что вы на самом деле хотите сделать с неверным вводом.

Есть также boost::lexical_cast (от руки я не знаю, как сделать это восьмеричным) и stringstream. Прочитайте нужный вам тип, а не тот, который имеет функцию библиотеки C для него.

Здесь вы не увидите никаких предупреждений, потому что типы данных "int" и "long int" на вашей платформе имеют одинаковый размер и диапазон. В зависимости от архитектуры они могут стать разными.

Чтобы защитить себя от странных ошибок, используйте проверку диапазона. Я предлагаю вам использовать std::numeric_limits::min/max (см.).

После проверки диапазона вы можете безопасно использовать static_cast или c-style cast.

С другой стороны, вы можете положиться на ту же функциональность, реализованную в классе std:: stringstream. Преобразование с помощью std:: stringstream будет безопасным для платформы и безопасным для типов по умолчанию.

Большинство современных компиляторов будут предупреждать о преобразовании и возможном усечении в зависимости от настроенного вами уровня предупреждения. На MSVC это уровень предупреждения 4.

Рекомендуется возвращать long из вашей функции, и позволить вызывающему коду решить, как обработать преобразование. За исключением этого, по крайней мере, убедитесь, что значение, возвращаемое вами из strtol, поместится в int, прежде чем вы вернетесь, как предполагает Let_Me_Be.

Другие вопросы по тегам