クロスプラットフォームのc/c ++プロジェクト(Win32、Linux、OSX)では、*printf関数を使用してsize_t型の変数を出力する必要があります。一部の環境ではsize_tは8バイトで、他の環境では4バイトです。glibcでは%zdがあり、Win32では%Idを使用できます。これを処理するエレガントな方法はありますか?
10 に答える
PRIuPTR
マクロ(<inttypes.h>から)は、の10進形式を定義します。これは、切り捨てることなくにuintptr_t
キャストできるように、常に十分な大きさである必要があります。size_t
fprintf(stream, "Your size_t var has value %" PRIuPTR ".", (uintptr_t) your_var);
ここで実際に 2 つの質問があります。最初の質問は、3 つのプラットフォームの正しい printf 指定子文字列は何かということです。size_t
は符号なしタイプであることに注意してください。
Windowsでは、" " を使用します%Iu
。
2 番目の質問は、プラットフォームごとにフォーマット文字列などが異なる可能性があることを考えると、複数のプラットフォームをサポートする方法です。他の人が指摘しているように、使用#ifdef
するとすぐに醜くなります。
代わりに、ターゲット プラットフォームごとに個別のメイクファイルまたはプロジェクト ファイルを記述します。次に、ソース ファイル内のマクロ名で指定子を参照し、各メイクファイルでマクロを適切に定義します。特に、GCC と Visual Studio の両方が、コマンド ラインでマクロを定義するための「D」スイッチを受け入れます。
ビルド システムが非常に複雑な場合 (複数のビルド オプション、生成されたソースなど)、3 つの個別の makefile を維持するのは扱いにくい場合があり、CMake や GNU autotools などの高度なビルド システムを使用する必要があります。ただし、基本原則は同じです。ソース ファイルにプラットフォーム検出ロジックを配置する代わりに、ビルド システムを使用してプラットフォーム固有のマクロを定義します。
私が考えることができる唯一のことは、典型的なものです:
#ifdef __WIN32__ // or whatever
#define SSIZET_FMT "%ld"
#else
#define SSIZET_FMT "%zd"
#endif
そして、定数畳み込みを利用します。
fprintf(stream, "Your size_t var has value " SSIZET_FMT ".", your_var);
Dan Saks は、Embedded Systems Design にこの問題を扱った記事を書きました。Dan によると、%zu は標準的な方法ですが、これをサポートしているコンパイラはほとんどありません。別の方法として、彼は %lu を引数の unsigned long への明示的なキャストと一緒に使用することを推奨しました。
size_t n; ... printf("%lu", (unsigned long)n);
を使用しboost::format
ます。タイプセーフなので、 でsize_t
正しく出力されます。また、使用時にs%d
を付けることを覚えておく必要はありません。また、 に数値を渡したり、その逆を行ったりしても機能します。c_str()
std::string
%s
満足のいく解決策はわかりませんが、size_tアイテムを文字列にフォーマットし、文字列を出力するための特殊な関数を検討することをお勧めします。
(あるいは、それを回避できる場合は、boost :: formatはこの種のことを簡単に処理します。)
最大のストレージクラスを持つ整数型を見つけ、それに値をキャストしてから、より大きな型に適切なフォーマット文字列を使用する必要があります。このソリューションは、size_tだけでなく、すべてのタイプ(ptrdiff_tなど)で機能することに注意してください。
使用したいのはuintmax_tとフォーマットマクロPRIuMAXです。Visual C ++の場合、Microsoftが提供していないため、c99互換のstdint.hおよびinttypes.hヘッダーをダウンロードする必要があります。
も参照してください
http://www.embedded.com/columns/technicalinsights/204700432
この記事は、フレデリコが引用した記事の誤りを訂正します。
その問題に対する私の選択は、単純に size_t 引数を unsigned long にキャストし、どこでも %lu を使用することです。これはもちろん、値が 2^32-1 を超えると予想されない場合に限られます。これが短すぎる場合は、いつでも unsigned long long にキャストして %llu としてフォーマットできます。
いずれにせよ、あなたの弦がぎこちなくなることはありません。