決32vs64ビットのC++
-
19-09-2019 - |
質問
を探していなければならないというニーズを確実に確C++のコードは32vs64ビット.私たちにしたいと思っていましたリーズナブルなソリューション-マクロが好奇心があればお知らの人々が考える場合が失敗する可能性があるというが、より良い関係ではないかと思います。だということでクロスプラットフォームに複数のコンパイラ環境です。
#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
感謝。
解決
残念ながら、主要なコンパイラを横切っ64分の32ビットを定義しないクロスプラットフォームのマクロは存在しません。これを行うための最も効果的な方法は次の通りである私を見つけました。
まず、私は自分の表現を選びます。私はENVIRONMENT64 / ENVIRONMENT32を好みます。それから私は、主要なコンパイラのすべては、それが64ビット環境だかないと、私の変数を設定することを使用するかどうかを決定するために使用するものを見つけます。
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif
別のより容易なルートは、単にコンパイラのコマンドラインからこれらの変数を設定することです。
他のヒント
template<int> void DoMyOperationHelper();
template<> void DoMyOperationHelper<4>()
{
// do 32-bits operations
}
template<> void DoMyOperationHelper<8>()
{
// do 64-bits operations
}
// helper function just to hide clumsy syntax
inline void DoMyOperation() { DoMyOperationHelper<sizeof(size_t)>(); }
int main()
{
// appropriate function will be selected at compile time
DoMyOperation();
return 0;
}
残念ながら、クロスプラットフォーム、クロスコンパイラ環境がないため信頼性高い方法でこれを純粋にコンパイルす。
- 両_WIN32と_WIN64であ 両 未定義の場合、プロジェクトの設定が不良または破損(特にVisual Studio2008SP1).
- プロジェクトラベルを付け"Win32"を設定することができまし64ビットの、プロジェクトの構成エラーになります。
- Visual Studio2008SP1ることも多かったことも頭に付けないグレーの正しいパーツのコードによると、現在の#define.ることは困難であり、正確に把握できる#define用コンパイルす。
そのため、 け 法を組み合わせる 3つの簡単なチェック:
- 1) コンパイル時間の設定, び;
- 2) 実行時のチェック, び;
- 3) 強固なコンパイル時にチェック.
簡易なセキュリティチェック1/3:コンパイル時間の設定
任意に選択方法 セット のに必要な#define可変となります。私はこの方法から@JaredPar:
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
簡易なセキュリティチェック2/3:実行時のチェック
メイン()をダブルチェックがsizeof()という:
#if defined(ENV64BIT)
if (sizeof(void*) != 8)
{
wprintf(L"ENV64BIT: Error: pointer should be 8 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 64-bit mode.\n");
#elif defined (ENV32BIT)
if (sizeof(void*) != 4)
{
wprintf(L"ENV32BIT: Error: pointer should be 4 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 32-bit mode.\n");
#else
#error "Must define either ENV32BIT or ENV64BIT".
#endif
簡易なセキュリティチェック3/3:強固なコンパイル時にチェック
一般規則は"毎#defineならでの#elseを生成するエラー".
#if defined(ENV64BIT)
// 64-bit code here.
#elif defined (ENV32BIT)
// 32-bit code here.
#else
// INCREASE ROBUSTNESS. ALWAYS THROW AN ERROR ON THE ELSE.
// - What if I made a typo and checked for ENV6BIT instead of ENV64BIT?
// - What if both ENV64BIT and ENV32BIT are not defined?
// - What if project is corrupted, and _WIN64 and _WIN32 are not defined?
// - What if I didn't include the required header file?
// - What if I checked for _WIN32 first instead of second?
// (in Windows, both are defined in 64-bit, so this will break codebase)
// - What if the code has just been ported to a different OS?
// - What if there is an unknown unknown, not mentioned in this list so far?
// I'm only human, and the mistakes above would break the *entire* codebase.
#error "Must define either ENV32BIT or ENV64BIT"
#endif
更新2017-01-17
コメント @AI.G
:
4年後だったので)できます。 実行時チェックをコンパイル時に静的主張する:static_assert(sizeof(void*)==4);.今ではすべてコンパイル時に :)
付録A
Incidentially、上記の規則に適応できる全てのコードベースの信頼性:
- 毎場合(計算書に終わる。"else"を生成する警告やエラーとなります。
- 各スイッチ()計算書に終わる"デフォルト"を生成する警告やエラーとなります。
そこで力をお考えのシングルの場合は、事前になるものである欠陥のある)ロジックは、"else"の部分を実行し、正しいコードです。
この技術は多くのその他)を書く30,000線プロジェクトを作成し、奥日から最初に展開され製品化した12ヶ月間となりました。
あなたは stdint.h
。特にINTPTR_MAX
では正確にあなたが必要とする値です。
#include <cstdint>
#if INTPTR_MAX == INT32_MAX
#define THIS_IS_32_BIT_ENVIRONMENT
#elif INTPTR_MAX == INT64_MAX
#define THIS_IS_64_BIT_ENVIRONMENT
#else
#error "Environment not 32 or 64-bit."
#endif
Microsoftのコンパイラの一部(全て?)のバージョンがstdint.h
が付属していません。それは、標準のファイルなので、なぜわかりません。ここでは、使用できるバージョンがあります: の<のhref = "のhttp:// msinttypes .googlecode.com / SVN /トランク/ stdint.h」のrel = "noreferrer"> http://msinttypes.googlecode.com/svn/trunk/stdint.h の
これは、開始のためのWindows上で動作しません。ロングスとint型を使用すると、32ビットまたは64ビット版のWindows用にコンパイルしているかどうか、両方の32ビットです。私は、ポインタのサイズは8バイトであるかどうかをチェックすることは、おそらく、より信頼性の高いルートであると思うだろう。
あなたはこれを行うことができます:
#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif
Try this:
#ifdef _WIN64
// 64 bit code
#elif _WIN32
// 32 bit code
#else
if(sizeof(void*)==4)
// 32 bit code
else
// 64 bit code
#endif
の "64ビットでコンパイル" はウェルC ++で定義されていません。の
C ++のようなint型、長いvoid *
ようなサイズのための唯一の下限を設定します。 intは64ビットプラットフォーム用にコンパイルされた64ビットの場合もあるという保証はありません。モデルは、例えば、を可能にします23ビットint
s及びsizeof(int *) != sizeof(char *)
noreferrer">プログラミングモデルは、64ビット・プラットフォーム用のをrel="nofollow href="http://www.unix.org/version2/whatsnew/lp64_wp.html"異なる
あなたの最善の策は、プラットフォーム固有のテストです。あなたの最良の第二、ポータブル決定は、より具体的でなければならない。のものをは64ビットます。
あなたのアプローチはあまりにも遠くはありませんでしたが、あなただけのlong
とint
は、同じサイズのものであるかどうかをチェックされています。理論的には、彼らは両方の32ビットとの両方を想定して、あなたのチェックが失敗した場合には64ビットである可能性があります。ここでは、実際の型そのものの大きさではなく、それらの相対的なサイズをチェックし、チェックがあります:
#if ((UINT_MAX) == 0xffffffffu)
#define INT_IS32BIT
#else
#define INT_IS64BIT
#endif
#if ((ULONG_MAX) == 0xfffffffful)
#define LONG_IS32BIT
#else
#define LONG_IS64BIT
#endif
原則として、あなたは最大値でマクロ定義されたシステムを持っている任意のタイプのためにこれを行うことができます。
標準も32ビットシステムでは、少なくとも64ビットであることlong long
を必要とすることを注、
人々は、すでにプログラムが32-bit
または64-bit
にコンパイルされているかどうかを判断しようとする方法を提案します。
そして、私はあなたがアーキテクチャでは、あなたはそれが(「リラックスする」)と思われるものであることを確認するために、C ++ 11の機能static_assert
を使用することができることを追加したい。
あなたがマクロを定義する代わりにそうます:
#if ...
# define IS32BIT
static_assert(sizeof(void *) == 4, "Error: The Arch is not what I think it is")
#elif ...
# define IS64BIT
static_assert(sizeof(void *) == 8, "Error: The Arch is not what I think it is")
#else
# error "Cannot determine the Arch"
#endif
コードの下には、最新の環境のために正常に動作します:
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define IS64BIT 1
#else
#define IS32BIT 1
#endif
すべてのあなたの環境でのプロジェクト構成を使用することができる場合、それは簡単に64ビットおよび32ビットのシンボルを定義するだろう。ですから、このようなプロジェクト構成を持っていると思います:
32ビットデバッグ
32ビットリリース
64ビットのデバッグ
64ビットリリース
EDIT:これらは、一般的な構成である構成を標的化さではありません。あなたが欲しいものは何でもそれらを呼び出すます。
あなたがそれを行うことができない場合は、、私はジャレッドのアイデアを気に入っています。
私は別のファイルで32ビットと64ビットのソースを配置し、ビルドシステムを使用して、適切なソースファイルを選択すると思います。
私はこの答えとして利用の場合、完全な例では、実行時のチェックに記載の 他の答え.
このアプローチしていを伝えるエンドユーザーかどうかのプログラム集として64ビットと32ビット(またはその他る):
バージョン。h
#ifndef MY_VERSION
#define MY_VERSION
#include <string>
const std::string version = "0.09";
const std::string arch = (std::to_string(sizeof(void*) * 8) + "-bit");
#endif
test.cc
#include <iostream>
#include "version.h"
int main()
{
std::cerr << "My App v" << version << " [" << arch << "]" << std::endl;
}
コンパイルおよび試験
g++ -g test.cc
./a.out
My App v0.09 [64-bit]