J’essaie de comprendre les exigences relatives à la sélection d’un type de données 64 bits intégré en utilisant long
ou long long
. J’ai du mal à comprendre l’équivalence de type et les exigences d’alignement de long
par rapport à long long
.
Quelle est la meilleure pratique ou les meilleurs critères lors de la sélection de type long
long long
64 bits avec les modèles de données LP64 / ILP64 / LLP64?
Voici quelques questions connexes. Ils couvrent complètement d’autres sujets, tels que sizeof(long) <= sizeof(long long)
, mais ils ne traitent pas tout à fait des attentes d’équivalence ou d’alignement. Ils dépendent également fortement de types non intégrés, comme uint64_t
.
Les informations d’arrière-plan correspondent au code suivant pour sélectionner un type 64 bits intégré à utiliser:
#if _LP64 || __LP64__ || _ILP64 || __ILP64__ typedef my_u64 unsigned long; #else typedef my_u64 unsigned long long; #endif
i686 et ARMv7 et les typedef my_u64 unsigned long long
conviennent bien avec typedef my_u64 unsigned long long
.
Premier cas de problème
Sur un ordinateur x86_64 (AMD64), si typedef my_u64 unsigned long
est typedef my_u64 unsigned long
(en raison de LP64
), il en résulte une erreur de compilation:
$ gcc -mrdrnd test.cc -o test.exe test.cc: In function 'int main(int, char**)': test.cc:18:22: error: invalid conversion from 'my_u64* {aka long unsigned int*}' to 'long long unsigned int*' [-fpermissive] _rdrand64_step(&val); ^ In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/x86insortingn.h:46:0, from test.cc:2: /usr/lib/gcc/x86_64-linux-gnu/4.9/include/imminsortingn.h:166:1: note: initializing argument 1 of 'int _rdrand64_step(long long unsigned int*)' _rdrand64_step (unsigned long long *__P) ^
Deuxième problème
Sur un ordinateur Aarch64 (ARM64), si typedef my_u64 unsigned long long
est en vigueur (pour corriger l’erreur x86_64), il en résulte une erreur de compilation:
$ gcc test.cc -o test.exe test.cc: In function 'int main(int, char**)': test.cc:21:16: error: invalid conversion from 'my_u64* {aka long long unsigned int*}' to 'const uint64_t* {aka const long unsigned int*}' [-fpermissive] vld1q_u64(val); ^ In file included from test.cc:4:0: /usr/lib/gcc/aarch64-linux-gnu/4.9/include/arm_neon.h:17003:1: note: initializing argument 1 of 'uint64x2_t vld1q_u64(const uint64_t*)' vld1q_u64 (const uint64_t *a) ^
$ cat test.cc #if __x86_64__ #include #elif __aarch64__ #include #include #endif #if _LP64 || __LP64__ typedef unsigned long my_u64; #else typedef unsigned long long my_u64; #endif int main(int argc, char* argv[]) { #if __x86_64__ my_u64 val; _rdrand64_step(&val); #elif __aarch64__ my_u64 val[2]; vld1q_u64(val); #endif return 0; }