与64位Linux相比,32位Linux系统如何处理long long int
?
在我的32位系统上,我使用C++ wrapper作为MPFR数据类型;这个包装器有一个为long int
而不是long long int
定义的构造函数。然而,在32位系统上,这段代码才有效:
long long int i=5LL;
mpreal myVar(i);
cout<< "this was constructed with a long long int:" <<myVar <<endl;
这怎么可能? 32位gcc是否以某种方式将long long int
转换为long int
mpreal
数据类型 具有构造函数的long long int
?如果上面的代码在64位Linux上运行,那么编译器会导致关于构造不明确的错误。
我知道有些人会告诉我不要在64位上使用long long int
,但不幸的是,我正在使用另一个库(odeint),其中内置了代码来构建我给定的多精度数据类型这种方式,所以我认为我不能改变它。
无论如何,long int
与64位的long int
完全相同吗?如果我转向mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode)
{
mpfr_init2(mp,prec);
mpfr_set_si(mp, u, mode);
}
,我会丢失数据吗?例如如果我创建自己的构造函数,如:
{{1}}
答案 0 :(得分:1)
我向mpreal.h的作者询问了这个问题(完整的答案是http://www.holoborodko.com/pavel/mpfr/#comment-7444),首先是关于在64x系统上为long long int
构建一个新的构造函数:
>Functions “mpfr_set_ui/si” should be fine.
>Basically constructor for “long long int” should be equivalent to “long int” one.
>GNU GCC system makes porting from x32 to x64 a little bit messy. It automatically
>upgrades integer types to x64 bits, which could easily break code being ported.
>The best workaround for GCC would be to use types with explicit number of bits:
>int32_t, int64_t from stdint.h. Then move from x32 to x64 would be painless.
>However neither authors of MPFR nor developers of numeric libraries follow this
>standard using “long long int”, “long int”, “intmax_t” all of which means different
>things on x32 and x64 in GCC world.
>There is some macro-logic in mpreal.h which tries to make things smooth:
>(a) for x32 builds we define additional constructors for int64_t (aka “long long int”
>or “intmax_t” )
>(b) for x64 builds we remove constructors for such type since “long int” is already
>64bit wide.
>Macro MPREAL_HAVE_INT64_SUPPORT plays only “suggestive” role, it is undefined
>automatically for x64 builds on GCC to avoid clash among integer types.
>The better way would be to detect bit resolution of all integer types at compile time
>(using macros or meta-magic similar to boost) and add suitable routines to mpreal
>class. This could easily grow to be more complex than mpreal itself :) .
>Maybe I will come up with better solution in future versions, any suggestions are
>welcome.
所以我认为在我的构造函数中构建OP会在x64系统上修复正常工作,但如果回到x32系统则需要再次删除,否则会导致冲突。原因是MPREAL_HAVE_INT64_SUPPORT
宏在32x上被定义,并且int64_t
的构造函数(在32x上也称为long long int
)被定义,因此添加另一个这样的构造函数将导致冲突;这也是我的代码在32系统上开箱即用的原因。在64x系统上MPREAL_HAVE_INT64_SUPPORT
宏未定义,并且由于long int
已经是64位宽,因此删除了此类构造函数,因此作者无需拥有long long int
构造函数。
答案 1 :(得分:0)
对于各种类型的尺寸,请检查C standard,long long
必须至少包含64位。
要查看编译器对您的代码的真正作用,您可以使用例如二进制文件(或中间对象文件)上的objdump -D
。
如果您从long long
投射到long
,那么在32位曲目上将丢失数据。
据我所知,编译器可能在确定使用哪个构造函数时遇到麻烦(基本上无法决定是使用ctor(int)
还是ctor(long int)
)。
修改强>
#include <stdint.h>
...
uint64_t x = 5;
mpreal myVar(i);
定义为c-tor(uint64_t)
(或者更好地表示可以找到明确的匹配) - 因为在64位arch上(unsigned) long int
等同于uint64_t
(对于glibc,它实际上是定义的因此)。该错误源于编译器在处理重载函数时使用的规则 - 有关更多信息,请参阅C++11 standard / draft。
一般来说,如果您希望代码可移植,则应使用inttypes.h
or stdint.h
中定义的类型 - 即C99 - 即uintXX_t
和intXX_t
。这些类型保证提供准确的宽度,请参阅上面的wiki链接以获取更多信息。