Selecting 'long' versus 'long long' as 64-bit type under LP64/ILP64/LLP64 data models?

99封情书 提交于 2019-12-12 21:29:52

问题


I'm trying to understand the requirements for selecting a built-in 64-bit data type using either long or long long. I'm having trouble understanding the type equivalence and the alignment requirements of long versus long long.

What is the best practice or criteria when selecting long versus long long as a 64-bit type under LP64/ILP64/LLP64 data models?


Here are some related questions. They completely cover other topics, like sizeof(long) <= sizeof(long long), but they don't quite have a treatment of equivalence or alignment expectations. They also rely heavily on non-built-in types, like uint64_t.

  • The UNIX System - 64bit and Data Size Neutrality
  • What's the difference between unsigned long/long/int in c/c++?
  • Better to use long or long long in 64 bit
  • Specifying 64-bit unsigned integer literals on 64-bit data models

The background information is code similar to the following to select a built-in 64-bit type to use:

#if _LP64 || __LP64__ || _ILP64 || __ILP64__
typedef my_u64 unsigned long;
#else
typedef my_u64 unsigned long long;
#endif

i686 and ARMv7 and below are fine with using typedef my_u64 unsigned long long.

First problem case

On a x86_64 (AMD64) machine, if typedef my_u64 unsigned long is in effect (due to LP64), then it results in a compile 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 a Aarch64 (ARM64) machine, if typedef my_u64 unsigned long long is in effect (to fix the x86_64 error), then it results in a compile 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;
}

来源:https://stackoverflow.com/questions/38681146/selecting-long-versus-long-long-as-64-bit-type-under-lp64-ilp64-llp64-data-m

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!