2009-08-17 6 views
5

タイトルが述べるように、アーキテクチャが32ビットか64ビットかを判断する上品で安全な方法がありますか?エレガントで、正確で、正確で、短く、きれいで、スマートな方法を考えることができます。安全であれば、標準、C89/C99、オペレーティングシステムの独立性の面で安全だと思います。アーキテクチャが32ビットか64ビットかを判断するためのエレガントで安全な方法

+13

は、質問があいまいです:あなたは(プログラムのコードが64ビットコードであるか、またはCPUは64ビットコードをサポートしているかどうかを知りたいのですつまり、コンパイル時またはなどランタイムテスト)? –

+6

コンパイル時または実行時に意味がありますか?特定のOSですか? –

+1

32ビットまたは64ビットアーキテクチャの意味を最初に定義しなければ、質問に答えることはできません。普遍的に受け入れられている定義はありません。 –

答えて

3

ポインタのサイズは実際にはテストするのには良いことではありません。標準のCではあまりテストの結果とは関係がありません。

私の提案は、Cが理解できるテスト((size_t)-1)、最大オブジェクトサイズである:

if ((size_t)-1 > 0xffffffffUL) 
    { 
      printf("> 32 bits\n"); 
    } 
    else 
    { 
      printf("<= 32 bits\n"); 
    } 

それは0xffffffffULより大きいなら、あなたは、原理的にはより有意義なテストのように思える2**32 - 1バイトを超えるオブジェクトを持つことができます「32ビット対64ビット」という厄介なものです。

(あなたがsize_tの最大値が唯一2**32 - 1であることを知っている場合たとえば、その後、mmap()に1または2ギガバイトよりも大きな領域にしようとしない点はありません。)

2

最も一般的な方法は、sizeof(void*)sizeof(int)をテストすることです(必ずしも同じである必要はありません)。

x86/x64 CPUのもう一つの可能​​性は、 'lm'フラグをテストすることです。存在する場合、CPUはAMD64命令セットを認識します。

+0

あなたが提案するのは、両方のサイズを見つけてアーキテクチャを決定することです。 'lm'フラグをテストするための他の提案は、Cでアセンブラコードが必要だと思っているのですか? – mtasic85

+1

私はコード内の特定の命令のテストしか見ていませんでした(それはアセンブラでした、はい)。しかし、多くのOSはユーザランドでCPUフラグを公開しています。例えば、Linuxは/ proc/cpuinfoにこの情報を与えます。しかし、これはOSに依存するコードになります。 – ypnos

+1

64ビットマシンで32ビットコンパイラのバージョンを実行している場合は、どうしてもうまくいかないでしょうか? – Matt

9

短い答え:なし

長い答え:それはあまりにも多くのOS /コンパイラの組み合わせに依存します。たとえば、実行時にはLinux上でprocファイルシステムに問い合わせることができますが、Windowsではレジスタに問い合わせることができます。

あなたがコンパイルに使用されているコンパイラは32/64ビットのようなものを使用して、ターゲット持っていることを証明することができます

bool is_32bit() { 
    return sizeof(int *) == 4; 
} 

bool is_64bit() { 
    return sizeof(int *) == 8; 
} 

この可能性いくつかの仮定の下で働く(例えば、それは、実行時に動作します)。あなたのプラットフォームにコンパイル時に#defineを検索することはできますが、それはよく知られている混乱です。

+0

最適化をオンにすると、実行時に評価されません。不要な32/64ビットのコードが削除されます。また、* bool *はC標準にはありません。 – jbcreix

+5

"また、boolはC標準にはありません。 - http://en.wikipedia.org/wiki/Stdbool.h –

+0

おっと - 偽、それはでC99の規格です。それでも、c99のこのような奇妙なことのために、おそらく質問で指定されているのはC89ではありません。 – jbcreix

7

あなたは(タグで示されているように)GCCを使用している場合は、それが64ビットシステムだかどうかを調べるために、コンパイル時のテスト

#if __SIZEOF_POINTER__ == 8 

として、テストすることができます。使用するGCCのバージョンが__SIZEOF_POINTER__であることを確認してから使用してください。

+1

これはGCCのコンパイル時の問題を解決しており、これまでのところOKです。 – mtasic85

+1

+0 dfaの答えはポータブルです(一度あなたの無関係なブールタイプを削除すると)、よりクリーンなコードになります。この関数は常にtrueまたはfalseを返し、コンパイラは不要なコードを削除します。 – jbcreix

2

安全で移植性の高い技術は、残念ながら不可能です(安全でポータブルなのはC標準のルールしか許さないためです)。

sizeof(int)いくつかの一般的なコンパイラでは、32ビットプラットフォームでは4、64ビットプラットフォームでは8が提供されますが、これは保証されません。 Cの標準では、intはターゲット上での計算にint型が「自然な」サイズでなければならないことを示しているため、64ビット環境でもsizeof(int)は4になりました。 '

sizeof(void*)は、ポインターがアドレススペース全体をアドレス指定するのに適切なサイズでなければならないため、より優れています。したがって、sizeof(void*)はあなたに4または8を適切に与える可能性があります。 技術的には、sizeofは何かを格納するのに必要なバイト数を与え、バイトは8ビットである必要はないので、これは保証されません。バイトは技術的にはアドレス可能なメモリの最小単位ですが、これは人が慣れているほとんどのプラットフォームではちょうど8ビットになります。アドレス可能な8ビットは非常に一般的ですが、私は16ビットのアドレス可能で16ビットのワードサイズのチップを扱います(sizeof(int) = 1)。 バイトサイズが8ビットでない場合、sizeof(void*)はさまざまな値を与えることができます。

一方、x86とx64(32ビットと64ビットPCプロセッサ)を区別しようとするだけなら、sizeof(void *)で十分でコンパイラ間で移植可能です。

+1

sizeof(void *)にCHAR_BITを掛けて、そのサイズをビット単位で求めることができます(標準では、表現のすべてのビットが値のビットであることを保証しません)。実際、現在のx86_64の実装では、仮想アドレスの48ビットの値)。 – caf

1

32ビットコードバンクのかデータバンク上の32ビット。 :-) 8086プロセッサは、20ビットのコードメモリを持つ16ビットのデータを持っていました。また、現代のHavardマシンはコード/データ分離と奇妙なことを行う...

あなたは、x86プロセッサのためのcpuid命令をチェックすることがあります。他のプロセッサーファミリーは、そのような命令を持っていないかもしれません... YMMV。 Cでは

1
int iedx; 

__asm 
{ 

mov eax, 0x80000001; 
cpuid; 
mov, iedx,edx; 
} 

    if (iedx & (1 << 29)) 
     { 
     return 1; 
     } 
    return 0; 
+0

ほとんどの場合、コンピュータアーキテクチャはx86およびx86_64ではなく汎用アーキテクチャを指します。このコードは標準ではなく、ポータブルではありません。 – osgx

関連する問題