我需要一种可移植的方式来打印size_t
类型的变量 n 的值。由于我使用ANSI C89,因此无法使用z
长度修饰符。我目前的做法是将值转换为long unsigned int
:
printf("%lu\n", (long unsigned int) n);
如果size_t
被定义为unsigned int
或long unsigned int
,我无法看到它会如何失败。演员安全吗?
答案 0 :(得分:2)
size_t n = foo();
printf("%lu\n", (long unsigned int) n);
前提是
size_t
被定义为unsigned int
或long unsigned int
...是否安全?
是的,演员阵容是安全的,没有未定义的行为,也没有关于C89,C99,C11的信息丢失。
但是,附带条件是不是真的?
假设size_t
的范围在unsigned long
范围内是非常合理的。添加编译时测试:ref
#include <limits.h>
#if defined(__STDC__)
#if defined(__STDC_VERSION__)
#if (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
#if SIZE_MAX > ULONG_MAX
#error Re-work printf size code
#endif
#endif
#endif
#endif
关键是当代码具有依赖性时 - 添加测试。即使它在今天和历史上所有已知机器都可以接受,但未来还是未知数。
C今天,凭借其巨大的灵活性确实允许SIZE_MAX > ULONG_MAX
,但它确实很少见。国际海事组织,SIZE_MAX > ULONG_MAX
是beyond the pale。
此类测试虽然可能很常见,但编写超级可移植代码根本不可行或预算不足。
#include <limits.h>
#if CHAR_BIT != 8 && CHAR_BIT != 16 && CHAR_BIT != 32 && CHAR_BIT != 64
#error Code depends on char size as a common power of 2.
#endif
我需要一种可移植的方法来打印size_t类型的变量n的值。
然而,要解决OP的顶级目标,可以编写一个简单的可移植辅助函数。
// This approach works with any unsigned type
void print_size_t(size_t n) {
if (n >= 10) print_size_t(n/10);
putchar((int) (n%10) + '0');
}
为避免递归,功能稍长:
#include <limits.h>
void print_size_t(size_t n) {
char buf[sizeof n * CHAR_BIT / 3 + 2]; // 1/3 is more than log2(10)
char *p = &buf[sizeof buf - 1]; // Start at end of buf[]
*p = '\0';
do {
p--;
*p = (char) (n%10 + '0');
n /= 10;
} while (n); // Use a do {} while so print_size_t(0) prints something
fputs(p, stdout);
}