重複の可能性:
fuint64_tをprintする方法は?
64ビットMac(Clangを使用)ではuint64_t
タイプがunsigned long long
であるのに対し、64ビットUbuntuではuint64_t
タイプがunsigned long
であるのはなぜですか?
これにより、printf
呼び出しを取得して、両方の環境でコンパイラー警告を出さないようにする(または実際に機能するようにする)ことが非常に困難になります。
マクロを使用して正しい文字列(#define LU
%llu
または%lu
のいずれか、およびその過程でprintf
文字列を少し醜くする)を選択しようとすることができますが、 Macは64ビットのワードサイズを持っていますが(したがって、_LP64
が定義されUINTPTR_MAX != 0xffffffff
)、それでも64ビットのint型にはlong long
を使用します。
// printf macro switch (for the uint64_t's)
#if UINTPTR_MAX == 0xffffffff
// 32-bit
# define LU "%llu"
#else
// assume 64-bit
// special case for OS X because it is strange
// should actually check also for __MACH__
# ifdef __Apple__
# define LU "%llu"
# else
# define LU "%lu"
# endif
#endif
マクロは<cinttypes>
ですでに定義されています。試してみてください
printf("%"PRIu64, x);
または、さらに良いことに、次のようなC++機能を使用します
std::cout << x;
これにより、変数タイプに適切な<<演算子が選択されます。
答えは、静的キャストを介して宣伝することです。
some_type i = 5;
printf("our value is: %llu", (unsigned long long)i);
_uint64_t
_の基になるタイプは、実際には64ビットである限り、実装がどのようなものでもかまいません。
明らかに、C++では、問題が解消されるため、printf
の代わりにiostreamを使用することをお勧めします。ただし、printf
に渡された値をキャストするだけで、タイプを常に正しくすることができます。
printf("%llu", static_cast<unsigned long long>(value));
残念ながら、標準はこれらのタイプのサイズについてあまり具体的ではありません...唯一の保証はsizeof(int) <= sizeof(long) <= sizeof(long long)
です。
あなたが言ったようにマクロを使うことができます、あるいは%zu
と%ju
タイプ(OSXでは両方とも64ビット)を印刷するために使われるsize_t
またはuintmax_t
を使ってみることができます、Ubuntuでテストしていません)。他に選択肢はないと思います。
他の人からBOOSTを使うように言われると思います。したがって、BOOSTに依存しないソリューションを提供するために:
私は同じ問題に頻繁に遭遇したので、%llu
や%lu
などのブランドの代わりに%sにフィードする独自のヘルパーマクロをあきらめて作成しました。また、適切な形式の文字列デザインを維持し、より優れた(そしてより一貫性のある)16進およびポインターの印刷を提供するのに役立つこともわかりました。 2つの注意点があります。
追加の書式設定パラメーター(左/右揃え、パディングなど)を簡単に組み合わせることができませんが、LU
マクロでも実際に組み合わせることができません。
このアプローチでは、文字列のフォーマットと印刷のタスクにオーバーヘッドが追加されます。ただし、パフォーマンスが重要なアプリを作成しましたが、MicrosoftのVisual C++デバッグビルド(内部検証と破損チェックがすべて行われるため、ヒープメモリの割り当てと解放に通常の約200倍の時間がかかる)を除いて、問題であることに気づいていません。
比較は次のとおりです。
printf( "Value1: " LU ", Value2: " LU, somevar1, somevar2 );
vs.
printf( "Value1: %s, Value2: %s", cStrDec(somevar1), cStrDec(somevar2) );
それを機能させるために、私は次のようなマクロとテンプレートのセットを使用しました。
#define cStrHex( value ) StrHex ( value ).c_str()
#define cStrDec( value ) StrDecimal( value ).c_str()
std::string StrDecimal( const uint64_t& src )
{
return StrFormat( "%u%u", uint32_t(src>>32), uint32_t(src) );
}
std::string StrDecimal( const int64_t& src )
{
return StrFormat( "%d%u", uint32_t(src>>32), uint32_t(src) );
}
std::string StrDecimal( const uint32_t& src )
{
return StrFormat( "%u", src );
}
std::string StrDecimal( const int32_t& src )
{
return StrFormat( "%d", src );
}
std::string StrHex( const uint64_t& src, const char* sep="_" )
{
return StrFormat( "0x%08x%s%08x", uint32_t(src>>32), sep, uint32_t(src) );
}
std::string StrHex( const int64_t& src, const char* sep="_" )
{
return StrFormat( "0x%08x%s%08x", uint32_t(src>>32), sep, uint32_t(src) );
}
// Repeat implementations for int32_t, int16_t, int8_t, etc.
// I also did versions for 128-bit and 256-bit SIMD types, since I use those.
// [...]
私の文字列フォーマット関数は、std :: stringに直接フォーマットする現在推奨されている方法に基づいています。これは次のようになります。
std::string StrFormatV( const char* fmt, va_list list )
{
#ifdef _MSC_VER
int destSize = _vscprintf( fmt, list );
#else
va_list l2;
va_copy(l2, list);
int destSize = vsnprintf( nullptr, 0, fmt, l2 );
va_end(l2);
#endif
std::string result;
result.resize( destSize );
if (destSize!=0)
vsnprintf( &result[0], destSize+1, fmt, list );
return result;
}
std::string StrFormat( const char* fmt, ... )
{
va_list list;
va_start( list, fmt );
std::string result = StrFormatV( fmt, list );
va_end( list );
return *this;
}