C vsnprintf与inttypes中宏的兼容性
我正在重写一些代码,以便与32位和64位体系结构兼容,但我遇到了vsnprintf调用的问题。在这两种体系结构上,vsnprintf似乎都不能正确处理inttypes.h中的固定大小整数类型 以下是相关代码:C vsnprintf与inttypes中宏的兼容性,c,printf,C,Printf,我正在重写一些代码,以便与32位和64位体系结构兼容,但我遇到了vsnprintf调用的问题。在这两种体系结构上,vsnprintf似乎都不能正确处理inttypes.h中的固定大小整数类型 以下是相关代码: void formatString(char *buffer, int size, char *format, ...) { va_list va; /* Format the data */ va_start( va, format ); vsnprin
void formatString(char *buffer, int size, char *format, ...)
{
va_list va;
/* Format the data */
va_start( va, format );
vsnprintf( (char *)buffer, size, format, va );
va_end( va );
}
int main(int argc, char *argv[])
{
char buffer[2048];
printf("The format string: %s\n", stringsLookup(0));
formatString(&buffer[0], sizeof(buffer), stringsLookup(0), 1, 2);
printf("The output string: %s\n", buffer);
return 0;
}
结果如下:
The format string: action=DoSomething&Val1=%"PRIx32"&Val2=%x
The output string: action=DoSomething&Val1=%"PRIx32"&Val2=1
您可以看到格式字符串的%“PRIx32”部分没有按预期替换为值“1”。这是一个已知的问题吗?附近有工作吗
我要提到的是,如果我在源代码中硬编码字符串,预处理器似乎会将“%PRIu32”转换为适用于体系结构的适当宏,并且对vsnprintf的调用也会起作用。不幸的是,我需要能够加载字符串
更新
一些额外的背景:当我从32位系统转移到64位系统时,我必须修正某些变量的大小。我宣布它们为uint32\t。我还更改了它们的打印位置,以清除编译器警告。先前使用的代码printf(“%lx”)
。我使用了printf(“%”PRIx32)
。我需要对vsnprintf进行类似的调用
如前所述,如果我在源代码中硬编码字符串,预处理器会将“%”PRIx32适当地转换为“%lx”或“%x”。不幸的是,当我不得不从文件中加载字符串时,我遇到了麻烦。预处理器在这方面帮不了我。
PRIx32
是一个宏,其名称不应以文本形式出现,即使是在格式字符串中。几乎可以肯定,您使用它是错误的,除非它扩展为包含“PRIx32”
的字符串(几乎可以肯定不会)
典型的用法是printf(“数字:%”PRIx32“…”,arg)代码>
在上面的典型习惯用法中,“Number:%”“PRIx32”…“
被扩展为,比如说,“Number:%”“lX”…“
,它通过C语法的特性相当于“Number:%lX…”
如果需要动态创建格式字符串,请使用strcat
或其他字符串操作功能。不要编写与“Number:%\”PRIx32\“…”等价的代码
请记住,PRIx32
将扩展为字符串文字,不要编写“%PRIx32”
,这是没有意义的
编辑:
如果您是从一个文件中加载格式字符串(我在45分钟前的评论中建议您提供的信息),那么在从中加载文件时,您必须自己进行替换。发明一种类似于printf的%语法的语法,编写自己的函数来识别它,并用运行程序的体系结构上正确的语法替换它
请注意,从安全性的角度来看,如果从文件加载格式字符串,则控制该文件的是谁
还要注意,printf(“编号:%llx\n”,(无符号长)e)代码>几乎总是有效的。如果编译器的整数类型比unsigned long long
宽,并且您使用了它,那么这只会让您失望。PRIx32
是一个宏,它的名称即使在格式字符串中也不应该以文本形式出现。几乎可以肯定,您使用它是错误的,除非它扩展为包含“PRIx32”
的字符串(几乎可以肯定不会)
典型的用法是printf(“数字:%”PRIx32“…”,arg)代码>
在上面的典型习惯用法中,“Number:%”“PRIx32”…“
被扩展为,比如说,“Number:%”“lX”…“
,它通过C语法的特性相当于“Number:%lX…”
如果需要动态创建格式字符串,请使用strcat
或其他字符串操作功能。不要编写与“Number:%\”PRIx32\“…”等价的代码
请记住,PRIx32
将扩展为字符串文字,不要编写“%PRIx32”
,这是没有意义的
编辑:
如果您是从一个文件中加载格式字符串(我在45分钟前的评论中建议您提供的信息),那么在从中加载文件时,您必须自己进行替换。发明一种类似于printf的%语法的语法,编写自己的函数来识别它,并用运行程序的体系结构上正确的语法替换它
请注意,从安全性的角度来看,如果从文件加载格式字符串,则控制该文件的是谁
还要注意,printf(“编号:%llx\n”,(无符号长)e)代码>几乎总是有效的。如果编译器的整数类型大于unsigned long long
,并且您使用它,那么这只会让您失望。什么是stringsLookup(0)
?它是一个“char*stringsLookup(int index)”函数,负责从外部资源加载字符串。它将加载的字符串是“action=DoSomething&Val1=%”“PRIx32”&Val2=%x”。这就是我在代码其他地方的printf语句中使用的内容,所以这就是我在这里使用的内容。我之所以问这个问题,是因为这可能是bug所在的地方,但我假设它在我的答案中。我认为该函数会有问题,这就是为什么我打印出它的返回值(格式字符串)。什么是stringsLookup(0)
?这是一个“char*stringsLookup(int-index)”函数,负责从外部资源加载字符串。它将加载的字符串是“action=DoSomething&Val1=%”“PRIx32”&Val2=%x”。这就是我在代码其他地方的printf语句中使用的内容,所以这就是我在这里使用的内容。我之所以问这个问题,是因为这可能是bug所在的地方,但我去假设它在我的答案中。我想这个函数会有问题,这就是为什么我打印出它的返回值(格式字符串)。@KeithThompson它这样做了,我会再做一次。谢谢你的改进。我不想动态创建字符串。我只想用“PRIx32”而不是