我有一个类型的变量size_t,我想用它打印printf().我使用什么格式说明符来便携地打印它?
在32位机器上,%u似乎是对的.我编译了g++ -g -W -Wall -Werror -ansi -pedantic,并没有警告.但是当我在64位机器中编译该代码时,它会产生警告.
size_t x = <something>;
printf( "size = %u\n", x );
warning: format '%u' expects type 'unsigned int',
but argument 2 has type 'long unsigned int'
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,警告会消失,如果我将其更改为%lu.
问题是,如何编写代码,以便在32位和64位机器上编译警告?
编辑:作为一种解决方法,我想一个答案可能是将变量"转换"为一个足够大的整数,比如说unsigned long,并使用打印%lu.这在两种情况下都有效.我在寻找是否还有其他想法.
Ada*_*eld 452
使用z修饰符:
size_t x = ...;
ssize_t y = ...;
printf("%zu\n", x); // prints as unsigned decimal
printf("%zx\n", x); // prints as hex
printf("%zd\n", y); // prints as signed decimal
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 85
看起来它取决于您正在使用的编译器(blech):
%zu(或者%zx,或者%zd显示它好像是签名等)%Iu(或%Ix,或者%Id不过再次证明人签署的等) -但作为CL V19(在Visual Studio 2015年),微软支持的%zu (见此回复到这条评论)...当然,如果你使用的是C++,你可以cout按照AraK的建议使用.
Joh*_*ode 58
对于C89,使用%lu并将值转换为unsigned long:
size_t foo;
...
printf("foo = %lu\n", (unsigned long) foo);
Run Code Online (Sandbox Code Playgroud)
对于C99及更高版本,请使用%zu:
size_t foo;
...
printf("foo = %zu\n", foo);
Run Code Online (Sandbox Code Playgroud)
Kei*_*son 11
在任何相当现代的 C 实现中,"%zu"打印类型值的正确方法是size_t:
printf("sizeof (int) = %zu\n", sizeof (int));
Run Code Online (Sandbox Code Playgroud)
格式"%zu"说明符是在 1999 年 ISO C 标准中添加的(并被 2011 年 ISO C++ 标准采用)。如果您不需要关心比这更旧的实现,那么您现在可以停止阅读。
如果您的代码需要移植到 C99 之前的实现,您可以将该值转换为unsigned long并使用"%lu":
printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));
Run Code Online (Sandbox Code Playgroud)
这不能移植到 C99 或更高版本,因为 C99 引入了long long和,因此比 更广泛的unsigned long long可能性。size_tunsigned long
抵制使用"%lu"或"%llu"不使用石膏的诱惑。用于实现的类型size_t是实现定义的,如果类型不匹配,则行为未定义。类似的东西printf("%lu\n", sizeof (int));可能“有效”,但它根本不便携。
原则上,以下内容应涵盖所有可能的情况:
#if __STDC_VERSION__ < 199901L
printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));
#else
printf("sizeof (int) = %zu\n", sizeof (int));
#endif
Run Code Online (Sandbox Code Playgroud)
在实践中,它可能并不总是正确工作。__STD_VERSION__ >= 199901L 应该保证它"%zu"是受支持的,但并非所有实现都一定是正确的,特别是因为__STD_VERSION__它是由编译器设置并由"%zu"运行时库实现的。例如,具有部分C99 支持的实现可能会实现long long并创建 的size_ttypedef unsigned long long,但不支持"%zu"。(这样的实现可能不会定义__STDC_VERSION__。)
有人指出微软的实现可以有32位unsigned long和64位size_t. Microsoft 确实支持"%zu",但该支持添加得相对较晚。另一方面,只有当特定值碰巧超过 时,转换为unsigned long才会出现问题,而这在实践中不太可能发生。size_tULONG_MAX
如果您能够假设相当现代的实现,只需使用"%zu". 如果您需要允许较旧的实现,这里有一个可适应各种配置的可移植程序:
#include <stdio.h>
#include <limits.h>
int main(void) {
const size_t size = -1; /* largest value of type size_t */
#if __STDC_VERSION__ < 199901L
if (size > ULONG_MAX) {
printf("size is too big to print\n");
}
else {
printf("old: size = %lu\n", (unsigned long)size);
}
#else
printf("new: size = %zu\n", size);
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一个打印“尺寸太大而无法打印”的实现(x86_64-w64-mingw32-gcc.exe -std=c90在 Windows/Cygwin 上)实际上支持unsigned long long作为 C90 之上的扩展,因此您也许可以利用它 - 但我可以想象 C99 之前的实现支持unsigned long long但不支持"%llu"。无论如何,该实现都支持"%zu"。
size_t根据我的经验,当我探索实现时,我只想在快速一次性代码中打印值,而不是在生产代码中打印值。在这种情况下,做任何有效的事情可能就足够了。
(问题是关于 C 的,但我会提到 C++std::cout << sizeof (int)可以在该语言的任何版本中正常工作。)
扩展Adam Rosenfield对Windows的回答.
我在VS2013 Update 4和VS2015预览版上测试了这段代码:
// test.c
#include <stdio.h>
#include <BaseTsd.h> // see the note below
int main()
{
size_t x = 1;
SSIZE_T y = 2;
printf("%zu\n", x); // prints as unsigned decimal
printf("%zx\n", x); // prints as hex
printf("%zd\n", y); // prints as signed decimal
return 0;
}
Run Code Online (Sandbox Code Playgroud)
VS2015生成二进制输出:
1
1
2
而由VS2013生成的那个说:
zu
zx
zd
注意:ssize_t是一个POSIX扩展,SSIZE_T在Windows数据类型中类似,因此我添加了<BaseTsd.h>参考.
此外,除了以下C99/C11标头外,所有C99标头都可在VS2015预览中使用:
C11 - <stdalign.h>
C11 - <stdatomic.h>
C11 - <stdnoreturn.h>
C99 - <tgmath.h>
C11 - <threads.h>
Run Code Online (Sandbox Code Playgroud)
此外,C11 <uchar.h>现已包含在最新预览中.
std::size_t s = 1024;
std::cout << s; // or any other kind of stream like stringstream!
Run Code Online (Sandbox Code Playgroud)
对于那些谈论用C++做这个并不一定支持C99扩展的人,我衷心推荐boost :: format.这使得size_t类型大小问题没有实际意义:
std::cout << boost::format("Sizeof(Var) is %d\n") % sizeof(Var);
Run Code Online (Sandbox Code Playgroud)
由于您不需要boost :: format中的大小说明符,因此您可以担心如何显示值.
| 归档时间: |
|
| 查看次数: |
266388 次 |
| 最近记录: |