タイトルが示すように、アーキテクチャが 32 ビットか 64 ビットかを判断するエレガントで安全な方法はありますか。エレガントであるということは、正確、正確、短く、きれいで、スマートな方法を考えることができるということです。安全とは、標準、C89/C99、およびオペレーティング システムの独立性という点で安全と考えてください。
7 に答える
短い答え:いいえ
長い答え: OS とコンパイラの組み合わせが多すぎることに依存します。たとえば、実行時に、Linux では proc ファイルシステムをクエリできますが、Windows ではレジスタをクエリできます。
次のようなものを使用して、コンパイルに使用されているコンパイラに 32/64 ビット ターゲットがあることを証明できます。
bool is_32bit() {
return sizeof(int *) == 4;
}
bool is_64bit() {
return sizeof(int *) == 8;
}
これは、いくつかの仮定の下で機能する可能性があります (実行時に機能するなど)。プラットフォームのコンパイル時間#define
を検索できますが、それはよく知られた混乱です。
(タグに示されているように) GCC を使用している場合は、コンパイル時のテストとしてテストできます。
#if __SIZEOF_POINTER__ == 8
64 ビット システムであるかどうかを調べます。使用している GCC のバージョンが定義__SIZEOF_POINTER__
されていることを確認してから使用してください。
ポインターのサイズは、実際にはテストするのに適したものではありません。標準 C では、とにかくそのテストの結果でできることはあまりありません。
私の提案は((size_t)-1)
、C が理解できる最大のオブジェクト サイズである test です。
if ((size_t)-1 > 0xffffffffUL)
{
printf("> 32 bits\n");
}
else
{
printf("<= 32 bits\n");
}
それより大きい場合0xffffffffUL
、原則としてバイトより大きいオブジェクトを持つことができ2**32 - 1
ます。これは、漠然とした「32ビット対64ビット」よりも意味のあるテストのようです。
(たとえば、 の最大値size_t
が のみであることがわかっている場合、1 または 2 GB を超える領域2**32 - 1
を試しても意味がありません。)mmap()
最も一般的な方法はsizeof(void*)
andをテストsizeof(int)
することです (必ずしも同じである必要はないことに注意してください)。
x86/x64 CPU での別の可能性は、'lm' フラグをテストすることです。存在する場合、CPU は AMD64 命令セットを理解します。
残念ながら、安全で移植可能な手法は不可能です (安全で移植可能な手法では、C 標準のルールしか使用できないため)。
sizeof(int)
より一般的なコンパイラのいくつかでは、32 ビット プラットフォームでは 4、64 ビット プラットフォームでは 8 となる場合がありますが、これは保証されていません。C標準が言うすべては、intがターゲットでの計算の「自然な」サイズであるべきであり、非常に多くのコンパイラが、「十分」であるという理由で、64ビットの世界でもsizeof(int)を4のままにしています。 .
sizeof(void*)
ポインターはアドレス空間全体をアドレス指定するのに適切なサイズでなければならないためです。sizeof(void*)
したがって、必要に応じて 4 または 8 を与える可能性があります。ただし、技術的には、 sizeof は何かを格納するために必要なバイト数を提供するため、これでも保証されません.1バイトは8ビットである必要はありません。技術的には、バイトはメモリのアドレス指定可能な最小単位であり、人々が慣れ親しんでいるほとんどのプラットフォームではたまたま 8 ビットです。8 ビット アドレス指定可能は非常に一般的ですが、私は 16 ビット アドレス指定可能で 16 ビット ワード サイズ ( sizeof(int)
1 も同様) のチップを使用しています。したがって、バイト サイズが 8 ビットでないsizeof(void*)
場合は、さまざまな値が得られる可能性があります。
一方、単に x86 と x64 (32 ビットと 64 ビットの PC プロセッサ) を区別しようとしている場合は、 sizeof(void*) で十分であり、コンパイラ間で移植可能です。
int iedx;
__asm
{
mov eax, 0x80000001;
cpuid;
mov, iedx,edx;
}
if (iedx & (1 << 29))
{
return 1;
}
return 0;
コード バンクの 32 ビットまたはデータ バンクの 32 ビット。:-) 8086 プロセッサは 16 ビットのデータと 20 ビットのコード メモリを持っていました。また、最新のHavardマシンは、コード/データの分離で奇妙なことを行います...
cpuid
x86 プロセッサの手順を確認してください。他のプロセッサファミリには、そのような命令がない場合があります... YMMV.