对于无符号算术类型,(type)-1
是最大值。由于您不知道类型的相对大小是多少,请转换为uintmax_t
:
#define UNSIGNED_TYPE_MAX(t) ((uintmax_t)(t)-1)
if ((uintmax_t)x > UNSIGNED_TYPE_MAX(size_t)) puts("too large");
签名类型没有这样的快捷方式。事实上,我认为在严格可移植的 C89 或 C99 中没有任何方法可以确定带符号类型的最大值,而不使用相应的常量,例如SSIZE_MAX
for ssize_t
。stdint.h
C99 为在 ISO C 中定义的类型中定义的算术设计的每种类型指定常量。对于在 POSIX 中定义但在标准 C 中没有定义的类型,在limits.h
;中有很多值。请注意,它们是类型预期的有效值的限制,而不是可以适合类型的限制。例如,如果size_t
是 32 位类型,则SIZE_MAX
保证为 2 32 -1,而SSIZE_MAX
可能小于 2 31-1 如果实现不支持任何大于此的字节数。
假设整数以二进制表示并且没有填充位,如果您将自己限制为 POSIX(其中始终为 8 ),这是安全的CHAR_BIT
,您可以通过计算类型的大小来推断最大值:是有符号类型中的一个符号位,其他一切都是值位。
#define SIGNED_TYPE_MAX(t) (((uintmax_t)1 << (sizeof(t) * CHAR_BIT - 1)) - 1)
请注意,诸如“加倍直到停止增长”或“推入位模式 0111…111”之类的东西是不可靠的。C 标准表示有符号类型的行为是未定义的,GCC 利用这一点对有符号类型的操作执行优化,如果发生溢出,可能会导致错误值。例如,它可能在一个更大的寄存器中执行计算,这样溢出就不会发生。