32位Linux与64位Linux和MPFR上的long long int

时间:2012-12-04 10:28:17

标签: c++ gcc mpfr

与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}}

2 个答案:

答案 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 standardlong 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_tintXX_t。这些类型保证提供准确的宽度,请参阅上面的wiki链接以获取更多信息。