Eu preciso lançar o resultado do strtol para int?
Pergunta
O código a seguir não dá um aviso com G ++ 4.1.1 e -Wall
.
int octalStrToInt(const std::string& s)
{
return strtol(s.c_str(), 0, 8);
}
Eu estava esperando um aviso porque o strtol retorna um long int
Mas minha função está apenas retornando uma planície int
. Outros compiladores podem emitir um aviso aqui? Devo lançar o valor de retorno para o INT neste caso como uma boa prática?
Solução
Você pode precisar do sinalizador -wconversão para ativar esses avisos. No entanto, não avisará sobre grandes -> int, pois eles têm o mesmo tamanho com o GCC (o valor não muda devido à conversão). Mas seria se você converter, por exemplo grandes -> curto
Suponho que simplesmente fazer um elenco não seria recomendado, pois isso apenas encobriria a possibilidade de bugs. Seria bom depois que você verificou que esse elenco não modificará o valor para apaziguar o compilador.
Outras dicas
A melhor abordagem é:
long x = strtol(...); assert(x <= INT_MAX); return (int)x;
Você precisa limits.h
e assert.h
Se você não tem acesso a boost::numeric_cast
, você pode escrever uma imitação simples:
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));
Na verdade, isso é um trapaceiro, pois não funciona para os tipos de destino de pontos flutuantes. min()
Não é o mesmo limite para eles que é para tipos inteiros, você precisa verificar contra +/- max()
. Exercício para o leitor.
Se você usa o Assert ou alguma outra manipulação de erros, depende do que você realmente deseja fazer com a entrada inválida.
Há também boost::lexical_cast
(Fora de lado, não sei como fazer essa leitura octal) e StringStream. Leia o tipo que você deseja, não o tipo que possui uma função de biblioteca C para ele.
Você não vê nenhum aviso aqui, porque os tipos de dados "int" e "long Int" em sua plataforma têm o mesmo tamanho e alcance. Dependendo da arquitetura, eles podem se tornar diferentes.
Para se proteger de erros estranhos, use a verificação do alcance. Eu sugiro que você use std :: numeric_limits :: min/max (veja).
Após a verificação do intervalo, você pode usar com segurança o STATIC_CAST ou o elenco do estilo C.
Por outro lado, você pode confiar na mesma funcionalidade implementada na classe STD :: StringStream. A conversão com Std :: StringStream será segura para a plataforma e segura por padrão por padrão.
A maioria dos compiladores modernos alertará sobre a conversão e o possível truncamento, dependendo do nível de aviso que você configurou. No MSVC que está alertando o nível 4.
A prática recomendada seria retornar muito da sua função e deixar o código de chamada decidir como lidar com a conversão. Exceto isso, pelo menos verifique se o valor que você recebe do strtol se encaixará em um INT antes de retornar, conforme sugerido por let_me_be.