0

long long int64 ビット Linux と比較して、32 ビット Linux システムは正確にどのように処理しますか?

私の 32 ビット システムでは、MPFR データ型にC++ ラッパーを使用しています。このラッパーには、 に対して定義されたコンストラクターがありますが、 で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と言って、どういうわけかキャストしますか? 上記のコードが 64 ビット Linux で実行されると、コンパイラーは構造があいまいであるというエラーを返します。long intmpreal

64ビットではまったく使用しないようにと言う人もいますlong long intが、残念ながら、これがコードに組み込まれている別のライブラリ(odeint)を使用して、指定された多精度データ型をこのように構築しているため、使用しません私は物事を変えることができるとは思わない.

とにかく64ビットlong long intとまったく同じですか?long intにキャストするとデータが失われ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);
}
4

2 に答える 2

1

これについて mpreal.h の作成者に尋ねました (完全な回答はhttp://www.holoborodko.com/pavel/mpfr/#comment-7444long long intにあります)。まず、64x システムでの新しいコンストラクターの構築に関して:

>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_SUPPORT32x ではマクロが定義され、int64_t(32x では別名long long int) のコンストラクターが定義されるため、別のそのようなコンストラクターを追加すると衝突が発生するためです。これが、私のコードが 32 システムですぐに使える理由でもあります。64x システムでは、MPREAL_HAVE_INT64_SUPPORTマクロは定義されておらず、そのようなコンストラクターlong intは既に 64 ビット幅であるため削除されているため、作成者がコンストラクターを持つ必要はありませんでしたlong long int

于 2012-12-05T10:07:40.687 に答える
0
  • さまざまなタイプのサイズについては、C標準を確認してくださいlong long。少なくとも64ビットで表す必要があります。

  • コンパイラが実際にコードをどのように処理するかを確認するには、たとえばobjdump -Dバイナリ(または中間オブジェクトファイル)で使用できます。

  • 32ビットアーチでは、からにキャストするとデータ失われます。long longlong

  • 私が理解している限り、コンパイラーは使用するコンストラクターを決定するのに問題があるかもしれません(基本的に使用するかどうかを決定することはできませんctor(int)ctor(long int)

編集:

#include <stdint.h>
...
uint64_t x = 5;
mpreal myVar(i);

が定義されているとおりに機能しc-tor(uint64_t)ます(または、明確な一致が見つかると言えます)-64ビットアーチでは、は(glibcの場合は実際にはそのように定義されています)(unsigned) long intと同等であるためです。uint64_tエラーは、オーバーロードされた関数を処理するときにコンパイラが使用するルールから発生します。詳細については、C++11標準/ドラフトを参照してください。

一般的に、コードを移植可能にする場合は、inttypes.hまたはstdint.hで定義された型を使用する必要があります。これはC99です。つまりuintXX_tintXX_t。これらのタイプは正確な幅を提供することが保証されています。詳細については、上記のwikiリンクを参照してください。

于 2012-12-04T16:06:19.490 に答える