printf和%lu与OS X上的%lu
printf and %llu vs %lu on OS X
可能重复:
如何打印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
已经在<cinttypes>
中为您定义了宏。尝试
printf("%"PRIu64, x);
或者,更好的是,使用像这样的C++功能
std::cout << x;
其将选择适当的<lt;变量类型的运算符。
答案是通过静态铸造进行推广:
some_type i = 5;
printf("our value is: %llu", (unsigned long long)i);
uint64_t
的底层类型可以是任何实现,只要它实际上是64位即可。
显然,在C++中,首选的解决方案是使用iostreams而不是printf
,因为这样问题就消失了。但是,您总是可以强制转换传递给printf
的值,以使类型始终正确:
printf("%llu", static_cast<unsigned long long>(value));
不幸的是,标准对这些类型的大小并不是很具体。。。唯一的保证是sizeof(int) <= sizeof(long) <= sizeof(long long)
。
你可以像你说的那样使用宏,也可以尝试使用%zu
或%ju
,它们用于打印size_t
和uintmax_t
类型(都是在OS X上的64位,尚未在Ubuntu上测试(。我认为没有其他选择。
我相信其他人会告诉你使用BOOST。因此,为了提供一种不依赖BOOST的解决方案:
我经常遇到同样的问题,所以我放弃了,并编写了自己的帮助宏,这些宏可以输入%s,而不是任何品牌的%llu
或%lu
或其他什么。我还发现它有助于维护一个合理的格式字符串设计,并提供更好(更一致(的十六进制和指针打印输出。有两个注意事项:
-
您不能简单地组合额外的格式化参数(左/右对齐、填充等(,但也不能用
LU
宏真正做到这一点。 -
这种方法确实为格式化和打印字符串的任务增加了额外的开销。然而,我写的是性能关键型应用程序,除了在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::字符串的方法,它看起来像这样:
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;
}
- Linux的Cpp上的计时器
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 物理键盘上的触发器按键
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 集合上的输出迭代器:assign和increment迭代器
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 对于set上的循环-获取next元素迭代器
- 如何从棋盘上的箱号中找到行和列
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- if数组上的随机数
- 向量上的线性搜索
- 位阵列上的快速AND运算
- 无法将 GLFW 库与 Ubuntu 18.04 上的头文件链接
- 为什么一个向量上的多线程操作很慢
- 64位机器上的C++内存对齐
- printf和%lu与OS X上的%lu