19

条件sizeofが true の場合はマクロを定義し、false の場合は何も実行しません (ただし、コンパイルは行います)。プリプロセッサが をサポートしsizeofている場合、次のようになります。

#if (sizeof(void*) <= sizeof(unsigned int)) // what goes here?
#  define POINTER_FITS_INTO_UINT
#endif

コンパイル時のアサーションを作成する方法を説明するページがいくつかあります (例: http://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ )。失敗します)、しかし、このアプローチを私が望むものに拡張する方法がわかりません。sizeof

4

9 に答える 9

15

あなたはそれをすることはできません。sizeof はコンパイル時の演算子です。#if と #define とプリプロセッサ関連。プリプロセッサはコンパイラの前に実行されるため、これは機能しません。ただし、マルチパス (つまり、前処理、ふりコンパイル、前処理、コンパイル) を可能にする難解なコンパイラ スイッチを見つけることができるかもしれませんが、公平を期すために、私はあなたがやりたいことをやろうとするのをあきらめます。それは機能することを意図したものではなく、単に機能しません。

最良の方法は、そのような定義をコンパイラに渡される -D コマンドとして設定することです。選択したものが正しいことを静的にアサートできます。この方法では、特定のコンパイル モード (例: PowerPC Release) などに対して外部でいくつかの定義をセットアップするだけで済みます。

于 2010-12-07T07:54:03.937 に答える
11

問題の正しい解決策は、C99標準ヘッダーを使用することです。

#include <stdint.h>
#include <inttypes.h>

#include <inttypes.h>からの資料が含まれているため、2つのうち1つだけが必要#include <stdint.h>です。ただし、の資料の多くは、およびを使用<inttypes.h>してフォーマットされたI/Oにのみ関連しています。scanf()printf()

推定条件を考えると:

#if (sizeof(void*) <= sizeof(unsigned int)) // what goes here?
#  define POINTER_FITS_INTO_UINT
#endif

あなたが求めているように見えるものは、次のように知られています。

uintptr_t

これは、任意のポインターを保持するのに十分な大きさの符号なし整数型です(つまり、C標準の任意のデータポインター。POSIXは、関数ポインターも保持するのに十分な大きさでなければならないという追加の規則を課します)。タイプuintptr_tはで定義されてい<stdint.h>ます。

その後、そのような値または生のポインタを出力する場合は、次の情報を使用できます<inttypes.h>

printf("Pointer = 0x%" PRIXPTR "\n", uintptr_value);
printf("Pointer = 0x%" PRIXPTR "\n", (uintptr_t)any_pointer);
于 2010-12-07T08:11:09.207 に答える
11

これは、Cでコンパイル時のアサーションを偽造する方法を説明しています。短いバージョンは、switchステートメントを使用することです。

#define COMPILE_TIME_ASSERT(pred)            \  
    switch(0){case 0:case pred:;}

predCでの偽のブール式のように、0と評価されると、コンパイラはエラーをスローします。

于 2012-02-14T21:48:20.640 に答える
6

C99を想定すると、使用できます

#include <limits.h>
#include <stdint.h>

#if UINTPTR_MAX <= UINT_MAX
...

sizeof (void *) <= sizeof (intptr_t) <= sizeof (int)これは、C 言語の正常な実装を意味します。

于 2010-12-07T09:27:02.437 に答える
4

質問には C++ ではなく C のタグが付けられていますが、C++0x では、プリプロセッサではなくコンパイラによってチェックされる静的アサーションのメカニズムが定義されていることを知っておくと役立つ場合があります。

ウィキペディアの例は特に関連性があります。

static_assert (sizeof(int) <= sizeof(T), "T is not big enough!")
于 2010-12-07T10:00:41.953 に答える
1

編集

気にしないでください。Steve Rowe が指摘したように、これらのプリプロセッサの値sizeofも同様に設定されるため、完全に一周しただけです。

はコンパイル時まで評価されないためsizeof、他のプリプロセッサ値に依存する必要があります。 これが私がそれを行う方法です:

#include <values.h>
#if PTRBITS <= INTBITS
#  define POINTER_FITS_INTO_UINT
#endif
于 2010-12-07T07:55:06.517 に答える
0

これを理解する 1 つの方法は、データ モデルの概念です (たとえば、http://sourceforge.net/p/predef/wiki/DataModels/を参照)。

LP32 ILP32 LP64 LLP64 ILP64 を含むいくつかのデータ モデルがあり、ほとんどのプラットフォームでは、cc フロントエンド コマンドが現在のモデルを定義します (たとえば、_ILP32 は int、long、およびポインターが 32 ビットであることを意味し、_LP64 は long およびポインターが 64 ビットであることを意味します)。

于 2015-08-12T20:02:02.547 に答える
0

ここで 2 つのコンパイル手順を混同しています。C プログラムをコンパイルするときの最初のステップは、インクルード、マクロ、および「#」で始まる行を解決するプリプロセッサです。次に、付随的に sizeof 式を評価するコンパイルが行われます。

これらは 2 つの異なるバイナリであり、そのタイプの情報を一方から他方に渡すことはできません。__i386__使用しているアーキテクチャを把握し、int とポインターのサイズを推測する場合は、または __x86_64__などのシステム定義のマクロを使用する必要があります。

于 2010-12-07T08:06:06.577 に答える