如果%在printf的格式字符串中没有后跟一个合适的字符怎么办?

时间:2012-04-29 14:26:28

标签: c printf

我正在尝试编写一个名为error的函数,其行为类似于printf,但仅支持%s,%c和%d说明符。但是,如果%后面没有合法字符,我无法理解printf的行为。我也尝试循环使用c99标准手册但找不到任何东西。有人可以帮助我吗?

3 个答案:

答案 0 :(得分:8)

C99在§7.19.6.1/ 9(fprintf)中有这个:

  

如果转换规范无效,则行为未定义。

因此,格式错误的格式字符串会导致未定义的行为。

如果格式字符串格式正确但参数实际上与类型不匹配,则相同:

  

如果任何参数不是相应转换规范的正确类型,则行为未定义。

答案 1 :(得分:0)

由于您似乎对实际发生的事情感兴趣,而不是您应该作为最佳做法所做的事情,我会解决这个问题并将其他人留给引用章和节。 : - )


格式字符串是printf的“提示”,告诉​​它要处理多少字节,以及如何格式化它们。如果你给它错误的格式,它会很乐意处理你告诉它的参数,无论它们的实际类型如何。

根据这些字节的值,它们可能有意义,或者它们可能是胡言乱语。

这是一个简单的(依赖于实现的)示例:

#include <stdio.h>

void main(int argc, char *argv[]) {
        int x = 10; // LF
        x <<= 8;
        x += 13;    // CR
        x <<= 8;
        x += 73;    // I
        x <<= 8;
        x += 72;    // H
        printf("x = %d (%08x)\n", x, x);
        printf("%.4s", &x);
}

这将x定义为(我的系统上的4字节)整数,其字节包含10 13 73 72`。这些字节恰好是换行符,回车符,I和H的ASCII码。

第一个printf显示x的小数和十六进制值,如果您自己计算它们,您会发现它们完全符合您的预期。

但第二个printfx视为4个字符的字符串。由于我的机器是little-endian,它会反转字节顺序,因此它会打印对应于ASCII 72,73,13,10的字符,这些字符是

H I CR LF

当然,正如Mat所说,这对于理解printf背后的机制很有用,但是你不应该编写依赖于这种行为的代码。至少,它不是可移植的(例如,大端机器不会改变字节顺序)。

答案 2 :(得分:0)

这取决于printf的编码方式。当在字符串中检测到%时,函数将找到它希望看到的一个字符。如果它匹配则它将处理匹配的块。例如,如果您将float传递给%d,那么它将处理传递整数的变量,以防参数纯粹通过堆栈传递。同样,如果将int传递给%f,它会将整数位解释为系统的特定浮点表示。

同样在注释中指出R ..在参数通过寄存器传递的情况下,输出将是不同的。存储传递值的寄存器类型(FPU寄存器或通用寄存器或其他)。某个格式说明符将首先获取它遇到的寄存器中的第一个参数。

如果角色不匹配,请说k,那么它可以只打印%k作为字符串,或者执行函数实现的任何内容。

修改

看看Mat关于此事的C99标准规范的答案。