9

重複の可能性:
どのように printf uint64_t?

64 ビット Mac (私は Clang を使用しています) ではuint64_tタイプが であるのにunsigned long long、64 ビット Ubuntu ではuint64_tタイプが であるのはunsigned longなぜですか?

printfこれにより、両方の環境でコンパイラの警告を出さないようにする (または実際に動作させる) ように呼び出しを取得することが非常に困難になります。

マクロを使用して正しい文字列を選択しようとすることができます (#define LUまたは%llu%luその過程でprintf文字列を少し_LP64醜くしますUINTPTR_MAX != 0xffffffff) 。 long long64 ビットの int 型を引き続き使用します。

// 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
4

5 に答える 5

7

マクロは、 ですでに定義されています<cinttypes>。試す

printf("%"PRIu64, x);

または、さらに良いことに、次のような C++ 機能を使用します。

std::cout << x;

これにより、変数の型に適した << 演算子が選択されます。

于 2012-12-28T18:40:38.897 に答える
4

答えは、静的キャストを介して昇格することです。

some_type i = 5;
printf("our value is: %llu", (unsigned long long)i);
于 2012-12-29T06:51:35.883 に答える
2

の基本的な型uint64_tは、実際に 64 ビットである限り、実装が好きなものであれば何でもかまいません。

printf明らかに C++ では、問題が解消される代わりに iostream を使用することをお勧めします。ただし、渡された値を常にキャストしprintfて、型を常に正しいものにすることができます。

printf("%llu", static_cast<unsigned long long>(value));

于 2012-12-28T18:40:47.747 に答える
0

BOOSTを使えと言う人もいると思います。したがって、BOOSTに依存しないソリューションを提供するために:

私は頻繁に同じ問題に遭遇したので、あきらめて、ブランドの%lluorなどの代わりに %s にフィードする独自のヘルパー マクロを作成しまし%luた。また、適切なフォーマット文字列の設計を維持し、より優れた (そしてより一貫性のある) 16 進数とポインターの出力を提供するのに役立つこともわかりました。2 つの注意事項があります。

  1. 追加の書式設定パラメーター (左右の位置合わせ、パディングなど) を簡単に組み合わせることはできませんが、実際にはLUマクロでもそれを行うことはできません。

  2. この方法では、文字列の書式設定と印刷のタスクに追加のオーバーヘッドが追加されます。ただし、私はパフォーマンスが重要なアプリを作成していますが、Microsoft の Visual C++ デバッグ ビルド (すべての内部検証と破損チェックのため、通常よりもヒープ メモリの割り当てと解放に約 200 倍の時間がかかります) を除いて、それが問題であることに気づいていません。

比較は次のとおりです。

printf( "Value1: " LU ", Value2: " LU, somevar1, somevar2 );

対。

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;
}
于 2012-12-28T19:12:03.787 に答える
0

残念ながら、標準はこれらの型のサイズについてあまり具体的ではありません...唯一の保証はsizeof(int) <= sizeof(long) <= sizeof(long long).

あなたが言ったようにマクロを使用することも、出力とタイプに使用される%zuorを使用することもできます(OS Xでは64ビット、Ubuntuではテストされていません)。他に選択肢はないと思います。%jusize_tuintmax_t

于 2012-12-28T18:41:07.853 に答える