Question

Je suis tombé sur quelque chose que je trouve plutôt étrange.Le programme des tests

int main(int argc, char* argv[])
{
    cout<<"hello"<<endl;
    long unsigned l = 0x12345678;
    long long unsigned ll =  0x12345678;
    cout<<sizeof(l)<<endl;
    cout<<sizeof(ll)<<endl;
};

la sortie est :

hello    
4    
8

Aucune surprise là-bas.Le long int a une taille de 4 octets et le long long a une taille de 8 octets.Cependant, quand je le change pour que le long long soit attribué

long long unsigned ll =  0x123456789;

au moment de la compilation, j'obtiens

error: integer constant is too large for "long" type

Maintenant ce même test fait compiler si je force une build 64 bits en utilisant l'option -m64.Est-ce que je fais quelque chose de mal ou est-ce un bug dans GCC ?

Était-ce utile?

La solution

Changez cela en

long long unsigned ll = 0x123456789ULL; // notice the suffix

Sans le suffixe, le littéral est plus grand que le maximum unsigned long valeur sur votre machine, et cela, selon C++03 (mais pas C++11, qui a long long), est un comportement indéfini.Cela signifie que tout peut arriver, y compris une erreur de compilation.

Ça ne vaut rien aussi qu'il n'y ait pas long long en C++03, son fonctionnement n'est donc pas garanti, vous comptez sur une extension.Vous feriez probablement mieux d’utiliser C++11 à la place.

Autres conseils

Le problème ici est que beaucoup de gens semblent regarder une ligne de code comme la vôtre :

unsigned long long ll = 0x123456789;   /* ANTI-PATTERN! Don't do this! */

et raison "oh, le type est unsigned long long, donc la valeur est unsigned long long et il est attribué", mais ce n'est tout simplement pas ainsi que C fonctionne.Littéraux ont leur propre type, cela ne dépend pas du contexte dans lequel ils sont utilisés.Et le type de littéraux entiers est int.

C’est la même erreur que lorsque les gens le font :

const double one_third = 1 / 3;   /* ANTI-PATTERN! Don't do this! */

Penser "le type à gauche est double, cela devrait donc attribuer 0,3333333...".Ce n’est (encore une fois !) pas ainsi que C fonctionne.Les types de littéraux divisés sont toujours int, donc le côté droit est évalué exactement à 0, qui est ensuite converti en double et stocké dans le one_third variable.

Pour une raison quelconque, ce comportement est profondément peu intuitif pour de nombreuses personnes, c'est pourquoi il existe de nombreuses variantes de la même question.

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