Comment peut-on static_cast entre unsigned int et int?
J'ai une de 8 caractères string
représentant un nombre hexadécimal et j'ai besoin de le convertir en un int
. Cette conversion a pour préserver le motif de bits pour les chaînes "80000000"
et plus, c'est à dire, ces chiffres devraient sortir négatif. Malheureusement, la naïve solution:
int hex_str_to_int(const string hexStr)
{
stringstream strm;
strm << hex << hexStr;
unsigned int val = 0;
strm >> val;
return static_cast<int>(val);
}
ne fonctionne pas pour mon compilateur si val > MAX_INT
(la valeur retournée est 0). Changer le type de val de int
également les résultats dans un 0 pour le plus grand nombre. J'ai essayé plusieurs solutions différentes de différentes réponses ici sur DONC et n'ai pas réussi encore.
Voici ce que je sais:
- Je suis en utilisant HP compilateur C++ sur OpenVMS (à l'aide, je crois, un processeur Itanium).
sizeof(int)
sera d'au moins 4 sur chaque architecture de mon code s'exécute.- Coulée à partir d'un nombre > INT_MAX int la mise en œuvre est définie. Sur ma machine, elle se traduit généralement par un 0, mais il est intéressant de noter casting de
long
àint
résultats dansINT_MAX
lorsque la valeur est trop grande.
C'est étonnamment difficile de le faire correctement, ou du moins il l'a été pour moi. Personne ne sait d'une portable solution?
Mise à jour:
Changer static_cast
à reinterpret_cast
génère une erreur de compilation. Un commentaire qui m'a incité à essayer un style C cast: return (int)val
dans le code ci-dessus, et cela a fonctionné. Sur cette machine. Volonté d'être toujours en sécurité sur d'autres architectures?
source d'informationauteur Michael Kristofik
Vous devez vous connecter pour publier un commentaire.
Bien qu'il existe de façons de le faire à l'aide de moulages et de conversions, plus compter sur un comportement indéfini qui arrive d'avoir bien défini les comportements sur certaines machines /avec certains compilateurs. Au lieu de compter sur un comportement indéfini, copier les données:
Citant le C++03 standard, §4.7/3 (Intégrale des Conversions):
Parce que le résultat est la mise en œuvre définies, par définition, il est impossible qu'il y ait une véritable portable solution.
Vous pouvez annuler un unsigned deux-complément de nombre en prenant le complément et d'en ajouter un. Donc, nous allons le faire pour les points négatifs:
Cela suppose que les entiers sont représentés avec 32-bit deux-en complément de la représentation (ou similaires). Il ne repose pas sur un comportement indéfini liées à débordement d'entier signé (à noter que le comportement de unsigned débordement d'entier est bien défini, bien que cela ne devrait pas arriver ici non plus!).
Notez que si votre ints ne sont pas de 32 bits, les choses deviennent plus complexes. Vous pouvez avoir besoin d'utiliser quelque chose comme
~(~0U >> 1)
au lieu de0x80000000
. De plus, si votre ints sont pas deux en complément, vous pouvez avoir des problèmes de débordement sur certaines valeurs (par exemple, sur un de ceux-complément de la machine,-0x80000000
ne peut être représenté dans un entier signé 32 bits). Cependant, la non-deux-complément de machines sont très rares aujourd'hui, donc c'est peu être un problème.Voici une autre solution qui a fonctionné pour moi:
Si je masque binaire élevé, je éviter tout débordement lors de la coulée. Je peux alors OU en arrière en toute sécurité.