Question

Le code suivant ne donne pas d'avertissement avec G ++ 4.1.1 et -Wall.

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

Je m'attendais à un avertissement parce que Strtol renvoie un long int Mais ma fonction ne renvoie qu'une plaine int. D'autres compilateurs pourraient-ils émettre un avertissement ici? Dois-je lancer la valeur de retour à INT dans ce cas comme une bonne pratique?

Était-ce utile?

La solution

Vous pourriez avoir besoin du drapeau -Conversion pour activer ces avertissements. Cependant, cela n'arrivera pas long -> int, car ils sont de la même taille avec GCC (la valeur ne changera pas à cause de la conversion). Mais ce serait si vous convertiz par exemple long -> court

Je suppose que le simple fait de faire un casting ne serait pas recommandé, car cela ne ferait que couvrir la possibilité de bugs. Ce serait OK après avoir vérifié qu'un tel casting ne modifiera pas la valeur pour apaiser le compilateur.

Autres conseils

La meilleure approche est:

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

Vous avez besoin limits.h et assert.h

Si vous n'avez pas accès à boost::numeric_cast, vous pouvez écrire une imitation simple:

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));

En fait, c'est un peu une triche, car cela ne fonctionne pas pour les types de destination à points flottants. min() n'est pas le même lié pour eux que pour les types entiers, vous devez vérifier contre +/- max(). Exercice pour le lecteur.

Que vous utilisiez Assert ou une autre manipulation des erreurs dépend de ce que vous voulez réellement faire pour une entrée non valide.

Il y a aussi boost::lexical_cast (Off-main, je ne sais pas comment faire l'octal en octal) et unstream. Lisez le type que vous souhaitez, pas le type qui a une fonction de bibliothèque C pour cela.

Vous ne voyez aucun avertissement ici, car les données "int" et "long int" sur votre plate-forme ont la même taille et la même gamme. Selon l'architecture, ils pourraient devenir différents.

Pour vous protéger des erreurs étranges, utilisez la vérification des plages. Je vous suggère d'utiliser STD :: Numeric_limits :: min / max (voir).

Après la vérification de la plage, vous pouvez utiliser en toute sécurité STATIC_CAST ou CAST de style C.

D'un autre côté, vous pouvez compter sur les mêmes fonctionnalités implémentées dans la classe Std :: StringStream. La conversion avec STD :: Stringstream sera par défaut de sécurité de la plate-forme et de type.

La plupart des compilateurs modernes mettront en garde contre la conversion et la troncature possible en fonction du niveau d'avertissement que vous avez configuré. Sur MSVC, c'est-à-dire le niveau 4.

La meilleure pratique serait de renvoyer un long de votre fonction et de laisser le code d'appel décider comment gérer la conversion. À moins de cela, assurez-vous au moins que la valeur que vous récupérez de Strtol s'intégrera dans un INT avant de revenir, comme suggéré par let_me_be.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top