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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top