C++ printf 和 %llu 与 OS X 上的 %lu

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14073877/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:57:21  来源:igfitidea点击:

printf and %llu vs %lu on OS X

c++macostypesintegerlong-integer

提问by Steven Lu

Possible Duplicate:
how to printf uint64_t?

可能重复:
如何打印 uint64_t?

Why is it that on my 64-bit Mac (I am using Clang) the uint64_ttype is unsigned long longwhile on 64-bit Ubuntu the uint64_ttype is unsigned long?

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

This makes it very difficult for me to get my printfcalls to not give compiler warnings (or indeed even to work) under both environments.

这使我很难printf在两种环境下调用不发出编译器警告(或什至无法正常工作)。

I can try to use macros to try to choose the correct string (#define LUeither %lluor %lu, and in the process uglifying the printfstrings a bit) but on the Mac I've got a 64-bit word size (so _LP64would be defined and UINTPTR_MAX != 0xffffffff) and yet it still uses long longfor the 64 bit int types.

我可以尝试使用宏来尽量选择正确的字符串(#define LU无论是%llu%lu,并在这个过程uglifying的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

采纳答案by Bo Persson

The macros are already defined for you in <cinttypes>. Try

宏已经在<cinttypes>. 尝试

printf("%"PRIu64, x);

Or, even better, use C++ features like

或者,更好的是,使用 C++ 功能,例如

std::cout << x;

which will select the proper << operator for your variable type.

这将为您的变量类型选择正确的 << 运算符。

回答by Grady Player

The answer is to promote via static cast:

答案是通过静态强制转换来提升:

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

回答by Mark B

The underlying type of uint64_tcan be whatever the implementation like as long as it is in fact 64 bits.

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

Obviously in C++ the preferred solution is to use iostreams instead of printfas then the problem disappears. But you can always just cast the value passed to printfto make the type always correct:

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

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

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

回答by daxnitro

Unfortunately the standard's not very specific on the sizes of these types... The only guarantee is that sizeof(int) <= sizeof(long) <= sizeof(long long).

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

You can use macros like you said, or you could try using %zuor %juwhich are used to print out size_tand uintmax_ttypes (both 64-bit on OS X, haven't tested on Ubuntu). I don't think there are any other options.

您可以像您说的那样使用宏,或者您可以尝试使用%zuor %juwhich 用于打印输出size_tuintmax_t类型(OS X 上均为 64 位,尚未在 Ubuntu 上测试)。我不认为还有其他选择。

回答by jstine

I'm sure other people will tell you to use BOOST. So in the interest of providing a solution that is not dependent on BOOST:

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

I have run into the same problem so often that I gave up and wrote my own helper macros that feed into %s instead of any brand of %lluor %luor whatever. I also found it helpful for helping maintain a sane format string design, and for providing better (and more consistent) hex and pointer printouts. There are two caveats:

我曾经常说我放弃了,写我自己的助手宏进料到%s,而不是任何品牌遇到了同样的问题%llu%lu或什么的。我还发现它有助于维护合理的格式字符串设计,以及提供更好(更一致)的十六进制和指针打印输出。有两个注意事项:

  1. You can't easily combine extra formatting parameters (left/right justification, padding, etc) -- but then you can't really do that with the LUmacro either.

  2. this approach does add additional overhead to the task for formatting and printing strings. However, I write performance-critical apps and I haven't noticed it being an issue except in Microsoft's Visual C++ debug builds (which take about 200x longer to allocate and free heap memory than normal because of all the internal validation and corruption checks).

  1. 您不能轻松地组合额外的格式参数(左/右对齐、填充等)——但是您也不能真正使用LU宏来做到这一点。

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

Here's a comparison:

这是一个比较:

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

vs.

对比

printf( "Value1: %s, Value2: %s", cStrDec(somevar1), cStrDec(somevar2) );

To make it work, I used a set of macros and templates like this:

为了使它工作,我使用了一组宏和模板,如下所示:

#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.
// [...]

My string formatting functions are based on the now-preferred method of formatting directly into a std::string, which looks something like this:

我的字符串格式化函数基于现在首选的直接格式化为 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;
}