Мне нужно передать результат 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.