14-可移植类型_stdint.h和inttypes.h
3.4.5 可移植类型: stdint.h
和 inttypes.h
C
语言提供了许多有用的整数类型。但是,某些类型名在不同系统中的功能不一样。 C99
新增了两个头文件 stdint.h
和 inttypes.h
,以确保 C
语言的类型在各系统中的功能相同。
C语言为现有类型创建了更多类型名。这些新的类型名定义在 stdint.h
头文件中。例如, int32_t
表示 32
位的有符号整数类型。在使用 32
位 int
的系统中,头文件会把 int32_t
作为 int
的别名。不同的系统也可以定义相同的类型名。例如, int
为 16
位、 long
为 32
位的系统会把 int32_t
作为 long
的别名。然后,使用 int32_t
类型编写程序,并包含 stdint.h
头文件时,编译器会把 int
或 long
替换成与当前系统匹配的类型。
上面讨论的类型别名是精确宽度整数类型(exact-width integer type
)的示例。 int32_t
表示整数类型的宽度正好是 32
位。但是,计算机的底层系统可能不支持。因此,精确宽度整数类型是可选项。
如果系统不支持精确宽度整数类型怎么办? C99
和 C11
提供了第 2
类别名集合。一些类型名保证所表示的类型一定是至少有指定宽度的最小整数类型。这组类型集合被称为最小宽度类型(minimum width type
)。例如, int_least8_t
是可容纳 8
位有符号整数值的类型中宽度最小的类型的一个别名。如果某系统的最小整数类型是 16
位,可能不会定义 int8_t
类型。尽管如此,该系统仍可使用 int_least8_t
类型,但可能把该类型实现为 16
位的整数类型。
当然,一些程序员更关心速度而非空间。为此, C99
和 C11
定义了一组可使计算达到最快的类型集合。这组类型集合被称为最快最小宽度类型(fastst minimum width type
)。例如, int_fast8_t
被定义为系统中对 8
位有符号值而言运算最快的整数类型的别名。
另外,有些程序员需要系统的最大整数类型。为此, C99
定义了最大的有符号整数类型 intmax_t
,可存储任何有效的有符号整数值。类似地, uintmax_t
表示最大的无符号整数类型。顺带一提,这些类型有可能比 long long
和 unsigned long
类型更大,因为C编译器除了实现标准规定的类型以外,还可利用C语言实现其他类型。例如,一些编译器在标准引入 long long
类型之前,已提前实现了该类型。
C99
和 C11
不仅提供可移植的类型名,还提供相应的输入和输出。例如, printf()
打印特定类型时要求与相应的转换说明匹配。如果要打印 int32_t
类型的值,有些定义使用 %d
,而有些定义使用 %ld
,怎么办? C
标准针对这一情况,提供了一些字符串宏(第 4
章中详细介绍)来显示可移植类型。例如, inttypes.h
头文件中定义了 PRId32
字符串宏,代表打印 32
位有符号值的合适转换说明(如 d
或 l
)。程序清单 3.6
演示了一种可移植类型和相应转换说明的用法。
程序清单3.6 altnames.c
程序
/* altnames.c -- 可移植整数类型名 */
#include <stdio.h>
#include <inttypes.h> // 支持可移植类型
int main(void)
{
int32_t me32; // me32是一个32位有符号整型变量
me32 = 45933945;
printf("First, assume int32_t is int: ");
printf("me32 = %d\n", me32);
printf("Next, let's not make any assumptions.\n");
printf("Instead, use a \"macro\" from inttypes.h: ");
printf("me32 = %" PRId32 "\n", me32);
return 0;
}
该程序最后一个 printf()
中,参数 PRId32
被定义在 inttypes.h
中的 "d"
替换,因而这条语句等价于:
printf("me32 = %" "d" "\n", me32);
在C语言中,可以把多个连续的字符串组合成一个字符串,所以这条语句又等价于:
printf("me32 = %d\n", me32);
下面是该程序的输出,注意,程序中使用了 \"
转义序列来显示双引号:
First, assume int32_t is int: me32 = 45933945
Next, let's not make any assumptions.
Instead, use a "macro" from inttypes.h: me32 = 45933945
篇幅有限,无法介绍扩展的所有整数类型。本节主要是为了让读者知道,在需要时可进行这种级别的类型控制。附录 B
中的参考资料 VI
“扩展的整数类型”介绍了完整的 inttypes.h
和 stdint.h
头文件。
注意 对C99/C11的支持
C
语言发展至今,虽然ISO
已发布了C11
标准,但是编译器供应商对C99
的实现程度却各不相同。在本书第6
版的编写过程中,一些编译器仍未实现inttypes.h
头文件及其相关功能。