我有一些C ++代码,它打印size_t
:
size_t a;
printf("%lu", a);
我想这不会对32位和64位架构的警告进行编译。
如果这是C99,我可以使用printf("%z", a);
。 但AFAICT %z
不以任何标准C ++方言存在。 所以不是,我必须这样做
printf("%lu", (unsigned long) a);
这实在是太丑了。
如果有打印无设施size_t
的建成到语言,我不知道它是否可以写一个printf包装或诸如此类,使得将插入适当的铸件上size_t
这么来消除伪编译器警告,同时仍保持良好的。
有任何想法吗?
为了澄清为什么我用printf:我有一个比较大的代码库,我清理。 它使用printf的包装做的事情,如“写一个警告,它记录到一个文件,并可能退出与一个错误代码”。 我也许能鼓起足够的C ++ - 富与COUT包装要做到这一点,但我宁愿没有改变的计划只是为了摆脱一些编译器警告的警告每()调用。
Answer 1:
大多数编译器对自己的符size_t
和ptrdiff_t
参数时,Visual C ++,例如使用的Iu%和%ID分别,我认为,GCC将允许您使用%祖和ZD%。
你可以创建一个宏:
#if defined(_MSC_VER) || defined(__MINGW32__) //__MINGW32__ should goes before __GNUC__
#define JL_SIZE_T_SPECIFIER "%Iu"
#define JL_SSIZE_T_SPECIFIER "%Id"
#define JL_PTRDIFF_T_SPECIFIER "%Id"
#elif defined(__GNUC__)
#define JL_SIZE_T_SPECIFIER "%zu"
#define JL_SSIZE_T_SPECIFIER "%zd"
#define JL_PTRDIFF_T_SPECIFIER "%zd"
#else
// TODO figure out which to use.
#if NUMBITS == 32
#define JL_SIZE_T_SPECIFIER something_unsigned
#define JL_SSIZE_T_SPECIFIER something_signed
#define JL_PTRDIFF_T_SPECIFIER something_signed
#else
#define JL_SIZE_T_SPECIFIER something_bigger_unsigned
#define JL_SSIZE_T_SPECIFIER something_bigger_signed
#define JL_PTRDIFF_T_SPECIFIER something-bigger_signed
#endif
#endif
用法:
size_t a;
printf(JL_SIZE_T_SPECIFIER, a);
printf("The size of a is " JL_SIZE_T_SPECIFIER " bytes", a);
Answer 2:
在printf
格式说明%zu
将正常工作在C ++系统; 没有必要使问题更加复杂。
Answer 3:
在Windows和printf的Visual Studio的实施
%Iu
我的作品。 看MSDN
Answer 4:
C ++ 11
C ++ 11吨的进口C99这样std::printf
应该支持C99 %zu
格式说明。
C ++ 98
在大多数平台上, size_t
和uintptr_t
是等效的,在这种情况下可以使用PRIuPTR
中定义的宏<cinttypes>
size_t a = 42;
printf("If the answer is %" PRIuPTR " then what is the question?\n", a);
如果你真的想成为安全,强制转换为uintmax_t
和使用PRIuMAX
:
printf("If the answer is %" PRIuMAX " then what is the question?\n", static_cast<uintmax_t>(a));
Answer 5:
由于您使用C ++,为什么不使用输入输出流? 这应该是你不是用脑死C ++实现,没有定义编译没有警告,并做正确的感知类型的东西,只要operator <<
用于size_t
。
当实际输出必须与完成printf()
你仍然可以用输入输出流结合起来,以获得类型安全的行为:
size_t foo = bar;
ostringstream os;
os << foo;
printf("%s", os.str().c_str());
这不是超高效的,但你的情况与上述交易文件I / O,所以这是你的瓶颈,不是这个字符串格式化代码。
Answer 6:
这里有一个可能的解决方案,但它不是一个相当漂亮的..
template< class T >
struct GetPrintfID
{
static const char* id;
};
template< class T >
const char* GetPrintfID< T >::id = "%u";
template<>
struct GetPrintfID< unsigned long long > //or whatever the 64bit unsigned is called..
{
static const char* id;
};
const char* GetPrintfID< unsigned long long >::id = "%lu";
//should be repeated for any type size_t can ever have
printf( GetPrintfID< size_t >::id, sizeof( x ) );
Answer 7:
有效类型底层为size_t是依赖于实现的 。 C标准将其定义为通过sizeof运算符返回的类型; 除了是无符号和一种整体式的,在为size_t可相当多的东西,其大小可容纳()预计将在的sizeof返回的最大价值。
要用于一个为size_t可以根据在服务器上改变因此,该格式串。 它应该始终有“U”形,但可能是L或d或也许别的...
一个小窍门可以将其转换为机器上的最大的整数类型,确保在转换没有损失,然后利用这种已知类型相关的格式字符串。
Answer 8:
在C ++格式库提供了一个快速便携(安全)实施printf
包括z
改性剂size_t
:
#include "format.h"
size_t a = 42;
int main() {
fmt::printf("%zu", a);
}
此外,它支持Python类格式字符串的语法和捕获类型信息,这样你就不必手动提供它:
fmt::print("{}", a);
它已经过测试与主要的编译器,并提供跨平台一致的输出。
免责声明 :我这个库的作者。
文章来源: Clean code to printf size_t in C++ (or: Nearest equivalent of C99's %z in C++)