101

を出力する C++ コードがいくつかありますsize_t

size_t a;
printf("%lu", a);

これを 32 ビット アーキテクチャと 64 ビット アーキテクチャの両方で警告なしでコンパイルしたいと思います。

これが C99 なら、 を使用できますprintf("%z", a);。しかし、AFAICT%zは標準の C++ 方言には存在しません。だから代わりに、私はしなければならない

printf("%lu", (unsigned long) a);

これは本当に醜いです。

sを印刷する機能が言語に組み込まれていない場合、適切なコンパイラ警告を維持しながら偽のコンパイラ警告を排除するためsize_tに、適切なキャストを s に挿入する printf ラッパーまたはそのようなものを作成できるかどうか疑問に思います。size_t

何か案は?


編集printfを使用している理由を明確にするために:クリーンアップしている比較的大きなコードベースがあります。printfラッパーを使用して、「警告を書き込み、ファイルに記録し、エラーでコードを終了する可能性があります」などのことを行います。cout ラッパーでこれを行うのに十分な C++-foo を集めることができるかもしれませんが、コンパイラーの警告を取り除くためだけに、プログラム内のすべての warn() 呼び出しを変更したくはありません。

4

9 に答える 9

71

printfフォーマット指定子は%zuC++ システムで正常に機能します。複雑にする必要はありません。

于 2009-11-03T18:28:50.410 に答える
61

ほとんどのコンパイラには独自の指定子size_tptrdiff_t引数があります。たとえば、Visual C++ ではそれぞれ %Iu と %Id を使用します。gcc では %zu と %zd を使用できると思います。

マクロを作成できます:

#if defined(_MSC_VER) || defined(__MINGW32__) //__MINGW32__ should goes before __GNUC__
  #define JL_SIZE_T_SPECIFIER    "%Iu"
  #define JL_SSIZE_T_SPECIFIER   "%Id"
  #define JL_PTRDIFF_T_SPECIFIER "%Id"
#elif defined(__GNUC__)
  #define JL_SIZE_T_SPECIFIER    "%zu"
  #define JL_SSIZE_T_SPECIFIER   "%zd"
  #define JL_PTRDIFF_T_SPECIFIER "%zd"
#else
  // TODO figure out which to use.
  #if NUMBITS == 32
    #define JL_SIZE_T_SPECIFIER    something_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_signed
    #define JL_PTRDIFF_T_SPECIFIER something_signed
  #else
    #define JL_SIZE_T_SPECIFIER    something_bigger_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_bigger_signed
    #define JL_PTRDIFF_T_SPECIFIER something-bigger_signed
  #endif
#endif

使用法:

size_t a;
printf(JL_SIZE_T_SPECIFIER, a);
printf("The size of a is " JL_SIZE_T_SPECIFIER " bytes", a);
于 2009-11-03T18:26:55.423 に答える
16

Windows および Visual Studio の printf の実装

 %Iu

私のために働きます。msdnを参照

于 2011-02-25T14:57:01.760 に答える
12

C++ を使用しているので、IOStreams を使用しないのはなぜですか? operator <<for を定義しない脳死状態の C++ 実装を使用していない限り、これは警告なしでコンパイルされ、正しい型認識を行うはずですsize_t

実際の出力を で行うprintf()必要がある場合でも、それを IOStreams と組み合わせてタイプ セーフな動作を得ることができます。

size_t foo = bar;
ostringstream os;
os << foo;
printf("%s", os.str().c_str());

それは非常に効率的ではありませんが、上記のケースはファイル I/O を扱っているため、この文字列フォーマット コードではなく、それがボトルネックです。

于 2009-10-10T01:40:30.703 に答える
7

ここに可能な解決策がありますが、それはかなりきれいなものではありません..

template< class T >
struct GetPrintfID
{
  static const char* id;
};

template< class T >
const char* GetPrintfID< T >::id = "%u";


template<>
struct GetPrintfID< unsigned long long > //or whatever the 64bit unsigned is called..
{
  static const char* id;
};

const char* GetPrintfID< unsigned long long >::id = "%lu";

//should be repeated for any type size_t can ever have


printf( GetPrintfID< size_t >::id, sizeof( x ) );
于 2009-10-10T09:11:35.980 に答える
3

size_tの基礎となる実効型は、実装に依存します。C 標準では、sizeof 演算子によって返される型として定義されています。符号なしで一種の整数型であることを除けば、size_t は、sizeof() によって返されると予想される最大値を収容できるサイズであれば、ほとんど何でもかまいません。

したがって、size_t に使用されるフォーマット文字列は、サーバーによって異なる場合があります。常に「u」が必要ですが、l または d または他の何かである可能性があります...

トリックは、マシン上で最大の整数型にキャストし、変換で失われないようにしてから、この既知の型に関連付けられた書式文字列を使用することです。

于 2009-10-10T01:48:37.600 に答える