Appearance
C 标准库 - <inttypes.h>
概述
<inttypes.h> 头文件扩展了 <stdint.h>,提供了用于格式化精确宽度整数类型的宏,以及整数转换函数。这是 C99 标准引入的头文件,对于跨平台编程中的格式化输出非常重要。
格式化宏
PRId8, PRIi8
int8_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int8_t value = 127;
printf("int8_t 值: %" PRId8 "\n", value);
printf("int8_t 值: %" PRIi8 "\n", value);
return 0;
}PRId16, PRIi16
int16_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int16_t value = 32767;
printf("int16_t 值: %" PRId16 "\n", value);
printf("int16_t 值: %" PRIi16 "\n", value);
return 0;
}PRId32, PRIi32
int32_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t value = 2147483647;
printf("int32_t 值: %" PRId32 "\n", value);
printf("int32_t 值: %" PRIi32 "\n", value);
return 0;
}PRId64, PRIi64
int64_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int64_t value = 9223372036854775807LL;
printf("int64_t 值: %" PRId64 "\n", value);
printf("int64_t 值: %" PRIi64 "\n", value);
return 0;
}PRIu8
uint8_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint8_t value = 255;
printf("uint8_t 值: %" PRIu8 "\n", value);
return 0;
}PRIu16
uint16_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint16_t value = 65535;
printf("uint16_t 值: %" PRIu16 "\n", value);
return 0;
}PRIu32
uint32_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint32_t value = 4294967295U;
printf("uint32_t 值: %" PRIu32 "\n", value);
return 0;
}PRIu64
uint64_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t value = 18446744073709551615ULL;
printf("uint64_t 值: %" PRIu64 "\n", value);
return 0;
}PRIx8, PRIX8
uint8_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint8_t value = 255;
printf("uint8_t 值: 0x%02" PRIx8 "\n", value);
printf("uint8_t 值: 0x%02" PRIX8 "\n", value);
return 0;
}PRIx16, PRIX16
uint16_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint16_t value = 65535;
printf("uint16_t 值: 0x%04" PRIx16 "\n", value);
printf("uint16_t 值: 0x%04" PRIX16 "\n", value);
return 0;
}PRIx32, PRIX32
uint32_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint32_t value = 4294967295U;
printf("uint32_t 值: 0x%08" PRIx32 "\n", value);
printf("uint32_t 值: 0x%08" PRIX32 "\n", value);
return 0;
}PRIx64, PRIX64
uint64_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t value = 18446744073709551615ULL;
printf("uint64_t 值: 0x%016" PRIx64 "\n", value);
printf("uint64_t 值: 0x%016" PRIX64 "\n", value);
return 0;
}PRIo8
uint8_t 的八进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint8_t value = 255;
printf("uint8_t 值: 0%03" PRIo8 "\n", value);
return 0;
}PRIo16
uint16_t 的八进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint16_t value = 65535;
printf("uint16_t 值: 0%06" PRIo16 "\n", value);
return 0;
}PRIo32
uint32_t 的八进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint32_t value = 4294967295U;
printf("uint32_t 值: 0%011" PRIo32 "\n", value);
return 0;
}PRIo64
uint64_t 的八进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t value = 18446744073709551615ULL;
printf("uint64_t 值: 0%022" PRIo64 "\n", value);
return 0;
}扫描宏
SCNd8, SCNi8
int8_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int8_t value;
printf("输入 int8_t 值: ");
scanf("%" SCNd8, &value);
printf("输入的值: %" PRId8 "\n", value);
return 0;
}SCNd16, SCNi16
int16_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int16_t value;
printf("输入 int16_t 值: ");
scanf("%" SCNd16, &value);
printf("输入的值: %" PRId16 "\n", value);
return 0;
}SCNd32, SCNi32
int32_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t value;
printf("输入 int32_t 值: ");
scanf("%" SCNd32, &value);
printf("输入的值: %" PRId32 "\n", value);
return 0;
}SCNd64, SCNi64
int64_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int64_t value;
printf("输入 int64_t 值: ");
scanf("%" SCNd64, &value);
printf("输入的值: %" PRId64 "\n", value);
return 0;
}SCNu8
uint8_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint8_t value;
printf("输入 uint8_t 值: ");
scanf("%" SCNu8, &value);
printf("输入的值: %" PRIu8 "\n", value);
return 0;
}SCNu16
uint16_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint16_t value;
printf("输入 uint16_t 值: ");
scanf("%" SCNu16, &value);
printf("输入的值: %" PRIu16 "\n", value);
return 0;
}SCNu32
uint32_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint32_t value;
printf("输入 uint32_t 值: ");
scanf("%" SCNu32, &value);
printf("输入的值: %" PRIu32 "\n", value);
return 0;
}SCNu64
uint64_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t value;
printf("输入 uint64_t 值: ");
scanf("%" SCNu64, &value);
printf("输入的值: %" PRIu64 "\n", value);
return 0;
}最大宽度类型宏
PRIdMAX, PRIiMAX
intmax_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
intmax_t value = 9223372036854775807LL;
printf("intmax_t 值: %" PRIdMAX "\n", value);
printf("intmax_t 值: %" PRIiMAX "\n", value);
return 0;
}PRIuMAX
uintmax_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uintmax_t value = 18446744073709551615ULL;
printf("uintmax_t 值: %" PRIuMAX "\n", value);
return 0;
}PRIxMAX, PRIXMAX
uintmax_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uintmax_t value = 18446744073709551615ULL;
printf("uintmax_t 值: 0x%016" PRIxMAX "\n", value);
printf("uintmax_t 值: 0x%016" PRIXMAX "\n", value);
return 0;
}SCNdMAX, SCNiMAX
intmax_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
intmax_t value;
printf("输入 intmax_t 值: ");
scanf("%" SCNdMAX, &value);
printf("输入的值: %" PRIdMAX "\n", value);
return 0;
}SCNuMAX
uintmax_t 的扫描宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uintmax_t value;
printf("输入 uintmax_t 值: ");
scanf("%" SCNuMAX, &value);
printf("输入的值: %" PRIuMAX "\n", value);
return 0;
}指针类型宏
PRIdPTR, PRIiPTR
intptr_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
intptr_t value = 12345;
printf("intptr_t 值: %" PRIdPTR "\n", value);
printf("intptr_t 值: %" PRIiPTR "\n", value);
return 0;
}PRIuPTR
uintptr_t 的格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uintptr_t value = 12345;
printf("uintptr_t 值: %" PRIuPTR "\n", value);
return 0;
}PRIxPTR, PRIXPTR
uintptr_t 的十六进制格式化宏。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
uintptr_t value = 0x12345678;
printf("uintptr_t 值: 0x%08" PRIxPTR "\n", value);
printf("uintptr_t 值: 0x%08" PRIXPTR "\n", value);
return 0;
}整数转换函数
imaxabs()
c
intmax_t imaxabs(intmax_t j);计算 intmax_t 的绝对值。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
intmax_t value = -12345;
intmax_t abs_value = imaxabs(value);
printf("原始值: %" PRIdMAX "\n", value);
printf("绝对值: %" PRIdMAX "\n", abs_value);
return 0;
}imaxdiv()
c
imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom);intmax_t 的整数除法。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
intmax_t numer = 12345;
intmax_t denom = 67;
imaxdiv_t result = imaxdiv(numer, denom);
printf("%" PRIdMAX " / %" PRIdMAX " = %" PRIdMAX "\n",
numer, denom, result.quot);
printf("%" PRIdMAX " %% %" PRIdMAX " = %" PRIdMAX "\n",
numer, denom, result.rem);
return 0;
}strtoimax()
c
intmax_t strtoimax(const char *nptr, char **endptr, int base);字符串转换为 intmax_t。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
const char* str = "1234567890";
char* endptr;
intmax_t value = strtoimax(str, &endptr, 10);
printf("字符串: %s\n", str);
printf("转换值: %" PRIdMAX "\n", value);
printf("剩余字符串: %s\n", endptr);
return 0;
}strtoumax()
c
uintmax_t strtoumax(const char *nptr, char **endptr, int base);字符串转换为 uintmax_t。
c
#include <stdio.h>
#include <inttypes.h>
int main() {
const char* str = "18446744073709551615";
char* endptr;
uintmax_t value = strtoumax(str, &endptr, 10);
printf("字符串: %s\n", str);
printf("转换值: %" PRIuMAX "\n", value);
printf("剩余字符串: %s\n", endptr);
return 0;
}wcstoimax()
c
intmax_t wcstoimax(const wchar_t *nptr, wchar_t **endptr, int base);宽字符串转换为 intmax_t。
c
#include <stdio.h>
#include <wchar.h>
#include <inttypes.h>
int main() {
const wchar_t* wstr = L"1234567890";
wchar_t* endptr;
intmax_t value = wcstoimax(wstr, &endptr, 10);
printf("转换值: %" PRIdMAX "\n", value);
return 0;
}wcstoumax()
c
uintmax_t wcstoumax(const wchar_t *nptr, wchar_t **endptr, int base);宽字符串转换为 uintmax_t。
c
#include <stdio.h>
#include <wchar.h>
#include <inttypes.h>
int main() {
const wchar_t* wstr = L"18446744073709551615";
wchar_t* endptr;
uintmax_t value = wcstoumax(wstr, &endptr, 10);
printf("转换值: %" PRIuMAX "\n", value);
return 0;
}实际应用示例
1. 跨平台日志
c
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
void log_message(const char* level, const char* message, intmax_t value) {
time_t now = time(NULL);
struct tm* tm = localtime(&now);
printf("[%04d-%02d-%02d %02d:%02d:%02d] [%s] %s: %" PRIdMAX "\n",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
level, message, value);
}
int main() {
log_message("INFO", "处理数据", 12345);
log_message("DEBUG", "内存使用", 65536);
log_message("ERROR", "错误代码", -1);
return 0;
}2. 网络协议解析
c
#include <stdio.h>
#include <inttypes.h>
typedef struct {
uint32_t sequence;
uint32_t timestamp;
uint16_t length;
uint8_t flags;
} PacketHeader;
void print_packet_header(const PacketHeader* header) {
printf("序列号: %" PRIu32 "\n", header->sequence);
printf("时间戳: %" PRIu32 "\n", header->timestamp);
printf("长度: %" PRIu16 "\n", header->length);
printf("标志: 0x%02" PRIx8 "\n", header->flags);
}
int main() {
PacketHeader header = {
.sequence = 1234567890,
.timestamp = 1704067200,
.length = 1024,
.flags = 0x0F
};
print_packet_header(&header);
return 0;
}3. 文件大小显示
c
#include <stdio.h>
#include <inttypes.h>
void print_file_size(uintmax_t size) {
const char* units[] = {"B", "KB", "MB", "GB", "TB"};
int unit_index = 0;
double display_size = size;
while (display_size >= 1024 && unit_index < 4) {
display_size /= 1024;
unit_index++;
}
printf("文件大小: %.2f %s (%" PRIuMAX " 字节)\n",
display_size, units[unit_index], size);
}
int main() {
print_file_size(1024);
print_file_size(1048576);
print_file_size(1073741824);
print_file_size(1099511627776ULL);
return 0;
}4. 内存地址显示
c
#include <stdio.h>
#include <inttypes.h>
void print_pointer(void* ptr) {
uintptr_t address = (uintptr_t)ptr;
printf("指针地址: 0x%016" PRIxPTR "\n", address);
}
int main() {
int value = 42;
int* ptr = &value;
print_pointer(ptr);
return 0;
}5. 十六进制转储
c
#include <stdio.h>
#include <inttypes.h>
void hex_dump(const uint8_t* data, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%02" PRIx8 " ", data[i]);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
printf("\n");
}
int main() {
uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
hex_dump(data, sizeof(data));
return 0;
}6. 大数计算
c
#include <stdio.h>
#include <inttypes.h>
uintmax_t factorial(uint8_t n) {
if (n == 0 || n == 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
for (uint8_t i = 0; i <= 20; i++) {
printf("%" PRIu8 "! = %" PRIuMAX "\n", i, factorial(i));
}
return 0;
}7. 时间戳转换
c
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
void print_timestamp(uint32_t timestamp) {
time_t t = timestamp;
struct tm* tm = localtime(&t);
printf("时间戳: %" PRIu32 "\n", timestamp);
printf("时间: %04d-%02d-%02d %02d:%02d:%02d\n",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
int main() {
print_timestamp(1704067200);
print_timestamp(1704153600);
return 0;
}8. 配置文件解析
c
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
void parse_config_line(const char* line) {
char key[100];
char value[100];
if (sscanf(line, "%99[^=]=%99s", key, value) == 2) {
if (strcmp(key, "max_size") == 0) {
uintmax_t max_size = strtoumax(value, NULL, 10);
printf("max_size = %" PRIuMAX "\n", max_size);
} else if (strcmp(key, "timeout") == 0) {
intmax_t timeout = strtoimax(value, NULL, 10);
printf("timeout = %" PRIdMAX "\n", timeout);
}
}
}
int main() {
parse_config_line("max_size=1048576");
parse_config_line("timeout=30");
return 0;
}9. 位操作
c
#include <stdio.h>
#include <inttypes.h>
void print_bits(uint32_t value) {
for (int i = 31; i >= 0; i--) {
printf("%" PRIu32, (value >> i) & 1);
if (i % 8 == 0 && i != 0) {
printf(" ");
}
}
printf("\n");
}
int main() {
uint32_t value = 0x12345678;
printf("值: 0x%08" PRIx32 "\n", value);
printf("二进制: ");
print_bits(value);
return 0;
}10. 版本号比较
c
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
typedef struct {
uint16_t major;
uint16_t minor;
uint16_t patch;
} Version;
int compare_versions(const Version* v1, const Version* v2) {
if (v1->major != v2->major) {
return v1->major > v2->major ? 1 : -1;
}
if (v1->minor != v2->minor) {
return v1->minor > v2->minor ? 1 : -1;
}
if (v1->patch != v2->patch) {
return v1->patch > v2->patch ? 1 : -1;
}
return 0;
}
void print_version(const Version* v) {
printf("版本: %" PRIu16 ".%" PRIu16 ".%" PRIu16 "\n",
v->major, v->minor, v->patch);
}
int main() {
Version v1 = {1, 2, 3};
Version v2 = {1, 2, 4};
Version v3 = {1, 2, 3};
print_version(&v1);
print_version(&v2);
printf("v1 vs v2: %d\n", compare_versions(&v1, &v2));
printf("v1 vs v3: %d\n", compare_versions(&v1, &v3));
return 0;
}注意事项
1. 格式化字符串拼接
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t value = 123456789;
printf("正确方式: %" PRId32 "\n", value);
return 0;
}2. 扫描宏的使用
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t value;
printf("输入值: ");
scanf("%" SCNd32, &value);
printf("输入的值: %" PRId32 "\n", value);
return 0;
}3. 跨平台兼容性
c
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t value = 123456789;
printf("int32_t 值: %" PRId32 "\n", value);
printf("int32_t 值: 0x%08" PRIx32 "\n", value);
printf("int32_t 值: 0%011" PRIo32 "\n", value);
return 0;
}4. 错误处理
c
#include <stdio.h>
#include <inttypes.h>
#include <errno.h>
#include <stdlib.h>
int main() {
const char* str = "123456789012345678901234567890";
char* endptr;
errno = 0;
uintmax_t value = strtoumax(str, &endptr, 10);
if (errno == ERANGE) {
printf("值超出范围\n");
} else {
printf("转换值: %" PRIuMAX "\n", value);
}
return 0;
}总结
<inttypes.h> 提供的格式化宏和转换函数对于跨平台编程非常重要:
- 跨平台兼容 - 确保在不同平台上正确格式化整数类型
- 类型安全 - 使用正确的格式化宏避免未定义行为
- 易于使用 - 提供了简单直观的接口
- 广泛应用 - 适用于网络协议、文件格式、日志等场景
记住:
- 始终使用格式化宏而不是硬编码的格式字符串
- 注意格式化字符串的正确拼接
- 使用扫描宏进行输入
- 检查转换函数的错误
- 根据需求选择合适的整数类型