我正在重写一些代码以与32位和64位体系结构兼容,而且我在vsnprintf调用中遇到了问题。看来vsnprintf在两种架构上都不能正确处理inttypes.h中的固定大小整数类型。
以下是相关代码:

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,还更改了它们的打印位置,以清除编译器警告。以前使用的代码printf("%lx")。我用了printf("%"PRIx32)。我需要对vsnprintf进行类似的调用。
如前所述,如果我在源代码中硬编码字符串,预处理器会将“%”PRIx32适当地转换为“%lx”或“%x”。不幸的是,当我不得不从文件中加载字符串时,我遇到了麻烦。预处理器帮不了我。

最佳答案

PRIx32是一个宏,其名称不应以文本形式显示,即使在格式字符串中也是如此。您几乎可以肯定使用它是错误的,除非它扩展到包含"PRIx32"的字符串(它几乎肯定不会)。
典型的用法是printf("Number: %" PRIx32 "...", arg);
在上面的典型习惯用法中,"Number: %" PRIx32 "..."被扩展为,比如说,"Number: %" "lX" "...",这是由C语法的一个特性等价于"Number: %lX..."
如果需要动态创建格式字符串,请使用strcat或其他字符串操作函数。不要写等同于"Number: %\"PRIx32\"..."的内容。
只要记住PRIx32扩展为字符串文本,并且不写"%PRIx32",这是没有意义的。
编辑:
如果要从文件加载格式字符串,我建议您在45分钟前在注释中提供的信息,则在从加载文件时,必须进行自己的替换。创建一个类似于printf的%语法的语法,并编写自己的函数来识别它,并用程序运行的体系结构上的正确内容替换它。
注意,从安全性的角度来看,如果从文件加载格式字符串,则控制文件的人controls what the program does
还要注意printf("Number: %llx\n", (unsigned long long) e);几乎总是有效的。只有当编译器的整数类型大于unsigned long long并且您使用它时,它才会让您失望。

09-08 04:34