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
printf and %llu vs %lu on OS X
提问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_t
type is unsigned long long
while on 64-bit Ubuntu the uint64_t
type 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 printf
calls 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 LU
either %llu
or %lu
, and in the process uglifying the printf
strings a bit) but on the Mac I've got a 64-bit word size (so _LP64
would be defined and UINTPTR_MAX != 0xffffffff
) and yet it still uses long long
for 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_t
can 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 printf
as then the problem disappears. But you can always just cast the value passed to printf
to 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 %zu
or %ju
which are used to print out size_t
and uintmax_t
types (both 64-bit on OS X, haven't tested on Ubuntu). I don't think there are any other options.
您可以像您说的那样使用宏,或者您可以尝试使用%zu
or %ju
which 用于打印输出size_t
和uintmax_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 %llu
or %lu
or 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
或什么的。我还发现它有助于维护合理的格式字符串设计,以及提供更好(更一致)的十六进制和指针打印输出。有两个注意事项:
You can't easily combine extra formatting parameters (left/right justification, padding, etc) -- but then you can't really do that with the
LU
macro either.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).
您不能轻松地组合额外的格式参数(左/右对齐、填充等)——但是您也不能真正使用
LU
宏来做到这一点。这种方法确实为格式化和打印字符串的任务增加了额外的开销。但是,我编写了对性能至关重要的应用程序,除了 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;
}