我的一个项目从 GCC 工具链切换到 clang 工具链编译时,发现原本的日志输出代码有些无法编译通过,是字符串格式化说明符与数据类型不匹配导致的。举个例子:
#include <stdio.h>
#include <stdint.h>
int main() {
uint32_t a = 0;
printf("1. %u\n", a);
printf("2. %ld\n", a);
return 0;
}
// 使用 GCC 编译时,会在 printf 1 处报错 (报错信息是另外的 ESP IDF 项目编译信息复制过来的,部分内容可能会不一样):
// error: format '%u' expects argument of type 'unsigned int', but argument 6 has type 'uint32_t' {aka 'long unsigned int'} [-Werror=format=]
// 使用 clang 编译时,会在 printf 2 处报错:
// error: format specifies type 'long' but the argument has type 'uint32_t' (aka 'unsigned int') [-Werror,-Wformat]
c在我这个项目中,uint32_t
在 GCC 下被解释为 long unsigned int
,而在 clang 下被解释为 unsigned int
。这种情况下,如果使用 "%ld"
来格式化输出 uint32_t
类型的变量,就会被 clang 编译器警告。
当然,不可能更换编译器就要将所有输出都修改一遍,所以我们可以使用 inttypes.h
头文件中定义的格式说明符来格式化输出。下面是一些常用的数据类型及其格式说明符 (包含了 size_t
):
数据类型 | 格式说明符 | 数据类型说明 |
---|---|---|
int8_t | PRId8 | 有符号 8 位整数 |
uint8_t | PRIu8 | 无符号 8 位整数 |
int_least8_t | PRIdLEAST8 | 至少 8 位的有符号整数 |
uint_least8_t | PRIuLEAST8 | 至少 8 位的无符号整数 |
int_fast8_t | PRIdFAST8 | 至少 8 为的最快有符号整数类型 |
uint_fast8_t | PRIuFAST8 | 至少 8 为的最快无符号整数类型 |
int16_t | PRId16 | 有符号 16 位整数 |
uint16_t | PRIu16 | 无符号 16 位整数 |
int_least16_t | PRIdLEAST16 | 至少 16 位的有符号整数 |
uint_least16_t | PRIuLEAST16 | 至少 16 位的无符号整数 |
int_fast16_t | PRIdFAST16 | 至少 16 位的最快有符号整数类型 |
uint_fast16_t | PRIuFAST16 | 至少 16 位的最快无符号整数类型 |
int32_t | PRId32 | 有符号 32 位整数 |
uint32_t | PRIu32 | 无符号 32 位整数 |
int_least32_t | PRIdLEAST32 | 至少 32 位的有符号整数 |
uint_least32_t | PRIuLEAST32 | 至少 32 位的无符号整数 |
int_fast32_t | PRIdFAST32 | 至少 32 位的最快有符号整数类型 |
uint_fast32_t | PRIuFAST32 | 至少 32 位的最快无符号整数类型 |
int64_t | PRId64 | 有符号 64 位整数 |
uint64_t | PRIu64 | 无符号 64 位整数 |
int_least64_t | PRIdLEAST64 | 至少 64 位的有符号整数 |
uint_least64_t | PRIuLEAST64 | 至少 64 位的无符号整数 |
int_fast64_t | PRIdFAST64 | 至少 64 位的最快有符号整数类型 |
uint_fast64_t | PRIuFAST64 | 至少 64 位的最快无符号整数类型 |
intmax_t | PRIdMAX | 有符号最大整数 |
uintmax_t | PRIuMAX | 无符号最大整数 |
intptr_t | PRIdPTR | 有符号的整数类型,其宽度足以容纳任何指针类型,用于将指针转换为整数,并在需要整数运算的情况下进行操作 |
uintptr_t | PRIuPTR | 无符号的整数类型,其宽度足以容纳任何指针类型,用于将指针转换为整数,并在需要整数运算的情况下进行操作 |
ptrdiff_t | PRIdPTR | 是有符号整数类型,用于存储两个指针之间的差值 |
size_t | "zu" | 无符号整数类型,用于存储对象的大小,其宽度足以容纳对象的大小 |
将上面的代码改成这样:
#include <stdio.h>
#include <inttypes.h>
#include <stdint.h>
int main() {
uint32_t a = 0;
printf("1. %" PRIu32 "\n", a);
return 0;
}
c这样就可以在不同编译器下都能正确输出 uint32_t
类型的变量了。
如果还要了解更多,可以点进你项目中的 inttypes.h
头文件中查看更多的格式说明符。