OS X上的printf和%llu vs%lu

时间:2012-12-28 18:15:16

标签: c++ macos types integer long-integer

  

可能重复:
  how to printf uint64_t?

为什么在我的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)但它仍然使用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

5 个答案:

答案 0 :(得分:6)

已在<cinttypes>中为您定义了宏。尝试

printf("%"PRIu64, x);

或者,更好的是,使用像

这样的C ++功能
std::cout << x;

将选择适当的&lt;&lt;变量类型的运算符。

答案 1 :(得分:3)

答案是通过静态演员推广:

some_type i = 5;
printf("our value is: %llu", (unsigned long long)i);

答案 2 :(得分:1)

uint64_t的基础类型可以是实现的任何类型,只要它实际上是64位。

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

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

答案 3 :(得分:0)

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

您可以像使用的那样使用宏,也可以尝试使用%zu%ju来打印size_tuintmax_t类型(均为64位)在OS X上,尚未在Ubuntu上测试过)。我认为还没有其他选择。

答案 4 :(得分:0)

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

我经常遇到同样的问题,所以我放弃并编写了自己的帮助宏,这些宏提供给%s,而不是任何品牌的%llu%lu或其他什么。我还发现它有助于维护一个理智的格式字符串设计,并提供更好(和更一致)的十六进制和指针打印输出。有两点需要注意:

  1. 您无法轻松组合额外的格式参数(左/右对齐,填充等) - 但是您无法使用LU宏执行此操作。

  2. 这种方法确实为格式化和打印字符串的任务增加了额外的开销。但是,我编写性能关键型应用程序并且我没有注意到它是一个问题,除了在Microsoft的Visual C ++调试版本中(由于所有内部验证和损坏检查,分配和释放堆内存的时间比正常大约200倍)。

  3. 以下是比较:

    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;
    }