9

可能重复:
如何打印 uint64_t?

为什么在我的 64 位 Mac(我正在使用 Clang)上uint64_t类型是unsigned long long64 位 Ubuntu 上的uint64_t类型是unsigned long

这让我很难printf在两种环境下都不给编译器警告(甚至不工作)。

我可以尝试使用宏来尝试选择正确的字符串(#define LUor %llu%lu并且在这个过程中稍微修改printf字符串)但是在 Mac 上我有一个 64 位的字长(所以_LP64会被定义和UINTPTR_MAX != 0xffffffff)但是它仍然long long用于 64 位 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 位。

显然,在 C++ 中,首选的解决方案是使用 iostreams 而不是printf问题消失。但是您总是可以只转换传递给的值printf以使类型始终正确:

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

于 2012-12-28T18:40:47.747 回答
0

不幸的是,标准对这些类型的大小不是很具体……唯一的保证是sizeof(int) <= sizeof(long) <= sizeof(long long).

您可以像您说的那样使用宏,或者您可以尝试使用%zuor%ju用于打印size_t和输入的宏uintmax_t(在 OS X 上都是 64 位,尚未在 Ubuntu 上测试)。我认为没有其他选择。

于 2012-12-28T18:41:07.853 回答
0

我相信其他人会告诉你使用 BOOST。因此,为了提供不依赖于 BOOST 的解决方案:

我经常遇到同样的问题,以至于我放弃并编写了自己的辅助宏来输入 %s 而不是任何品牌的%llu%lu或其他什么。我还发现它有助于保持健全的格式字符串设计,并提供更好(和更一致)的十六进制和指针打印输出。有两个警告:

  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 回答