I am trying to understand the requirements for choosing a built-in 64-bit data type using long or long long . I'm having trouble understanding type equivalence and long alignment requirements compared to long long .
What is the best practice or criteria when choosing long versus long long as a 64-bit type in LP64 / ILP64 / LLP64 data models?
Here are some related questions. They cover other topics completely, such as sizeof(long) <= sizeof(long long) , but they do not quite agree with the expectations of equivalence or alignment. They are also heavily dependent on non-built-in types such as uint64_t .
- UNIX system - 64 bit and data size neutral
- What is the difference between unsigned long / long / int in c / c ++?
- Better to use a long or long long 64-bit file
- Specifying unsigned 64-bit integer literals in 64-bit data models
Background information is code similar to the following to select the built-in 64-bit type:
#if _LP64 || __LP64__ || _ILP64 || __ILP64__ typedef my_u64 unsigned long; #else typedef my_u64 unsigned long long; #endif
i686 and ARMv7 and below are suitable using typedef my_u64 unsigned long long .
First problem case
On an x86_64 machine (AMD64), if typedef my_u64 unsigned long is valid (due to LP64 ), this leads to a compilation error:
$ 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/x86intrin.h:46:0, from test.cc:2: /usr/lib/gcc/x86_64-linux-gnu/4.9/include/immintrin.h:166:1: note: initializing argument 1 of 'int _rdrand64_step(long long unsigned int*)' _rdrand64_step (unsigned long long *__P) ^
Second problem case
On an Aarch64 machine (ARM64), if typedef my_u64 unsigned long long is valid (to fix the x86_64 error), this leads to a compilation error:
$ 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 <x86intrin.h> #elif __aarch64__ #include <arm_neon.h> #include <arm_acle.h> #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; }
c gcc long-integer 64bit long-long
jww
source share