Quel initialiseur est approprié pour un int64_t?

J’aime initialiser mes variables à une valeur “fictive” et j’ai commencé à utiliser int64_t et uint64_t . Jusqu’à présent, il semble qu’il y ait au moins trois manières d’initialiser un int64_t sur une valeur particulière (et avec de légères modifications pour l’équivalent non signé):

 int64_t method_one = 0; int64_t method_two = 0LL; int64_t method_three = INT64_C(0); 

J’utilise GCC et cible OS X et Linux. Je voudrais choisir une méthode qui vise à faciliter la portabilité et la clarté – mais la rectitude, avant tout. Est-ce que j’y pense trop, ou existe-t-il une approche “meilleure” ou “la plus recommandée” pour initialiser ce type de variable, pour une valeur particulière que je lui atsortingbue (ce qui est dans ses limites, bien sûr)?

 int64_t method_one = 0; 

… est parfaitement raisonnable. C99 (voir par exemple le brouillon ici ; oui, je sais que ce n’est plus la norme la plus récente, mais c’est celle qui a introduit les types int_t ):

  • le 0 a le type int (§6.4.4.1, paragraphe 5);
  • le type de l’expression est int64_t (§6.5.16, paragraphe 3);
  • le type du membre de droite sera converti en type de l’expression (§6.5.16.1, paragraphe 2);
  • cette conversion ne changera pas la valeur (§6.3.1.3 para.1).

Il n’ya donc rien de mal à cela, et le manque d’encombrement supplémentaire en fait l’option la plus lisible lors de l’initialisation à 0 ou toute autre valeur de l’intérieur d’un int .

 int64_t method_two = 0LL; 

int64_t n’est pas garanti que int64_t soit identique long long . cependant, cela devrait en fait fonctionner de manière portable pour toute valeur 64 bits signée (et de la même façon, ULL pour les valeurs 64 bits non signées): long long (et unsigned long long ) devrait être d’au moins 64 bits dans une implémentation conforme à C99 ( §5.2.4.2.1), donc LL (et ULL ) devraient toujours être sûrs pour l’initialisation de valeurs 64 bits.

 int64_t method_three = INT64_C(0); 

C’est sans doute une meilleure option pour les valeurs pouvant se situer en dehors de la plage d’un int , car elle exprime l’intention plus clairement: INT64_C(n) passera à quelque chose d’approprié pour toute plage n (au moins) de 64 bits (voir plus INT64_C(n) §7.18 en général, et en particulier §7.8.4.1).


En pratique, je pourrais bien utiliser l’un des éléments ci-dessus, selon le contexte. Par exemple:

 uint64_t counter = 0; 

(Pourquoi append un fouillis inutile?)

 uint64_t some_bit = 1ULL << 40; 

( 1 << 40 ne fonctionnera tout simplement pas à moins que int ne soit exceptionnellement large; et UINT64_C(1) << 40 me semble moins lisible ici.)

 uint64_t some_mask = UINT64_C(0xFF00FF00FF00FF00); 

(Dans ce cas, appeler explicitement la valeur sous forme de constante 64 bits me semble plus lisible que d'écrire 0xFF00FF00FF00FF00ULL .)

Personnellement, je voudrais utiliser le troisième, qui est le moyen le plus portable pour y parvenir.

 #include  int64_t method_three = INT64_C(0); uint64_t method_three = UINT64_C(0); 

En tout cas, je ne pense pas que ce soit une chose très importante.

Selon la norme ANSI C, les suffixes long long int et unsigned long long int sont respectivement LL et ULL :

octal ou hexadécimal suffixé par ll ou LL long long int, unsigné long long int décimal, octal ou hexadécimal suffixé par u ou U, et ll ou LL unsigned long long int

Si vous savez que int64_t est défini comme:

 typedef signed long long int int64_t 

Alors la méthode deux est certainement la bonne:

 int64_t method_two = 0LL; uint64_t method_two = 0ULL; 

Modifier :

En gardant à l’esprit les problèmes de portabilité et le fait que la définition ne soit pas long long , il serait préférable d’utiliser la troisième méthode:

 INT64_C() UINT64_C()