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

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

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

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

Ответ 1

Для включения этих предупреждений может понадобиться флаг -Wconvert. Однако он не будет предупреждать о длинных int, поскольку они имеют одинаковый размер с GCC (значение не изменится из-за преобразования). Но если бы вы конвертировали, например, длинный короткий

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

Ответ 2

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

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

Вам нужны limits.h и assert.h

Ответ 3

Если у вас нет доступа к 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.

Ответ 4

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

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

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

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

Ответ 5

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

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