我正在尝试编写一个名为 error 的函数,它的行为类似于 printf,但仅支持 %s、%c 和 %d 说明符。但是如果 % 后面没有合法字符,我无法理解 printf 的行为。我还尝试循环 c99 标准手册,但找不到任何东西。有人可以帮帮我吗?
3 回答
C99 在 §7.19.6.1/9 中有这个(对于fprintf
):
如果转换规范无效,则行为未定义。
因此,格式错误的格式字符串会导致未定义的行为。
如果格式字符串格式正确但参数实际上与类型不匹配,则相同:
如果任何参数不是相应转换规范的正确类型,则行为未定义。
It will depend on how the printf
is coded. When the %
is detected in the string the function will find for one of the characters it expects to see. If it matches then it will process the matched block. For example if you pass the float
to %d
then it will process the variable you passed an integer in case the arguments are purely passed through stack. Similarly if you pass an int
to %f
it will interpret the integer bits as the specific floating point representation of the system.
Also as R.. pointed out in the comment, in the case when the arguments are passed through registers the output will be different. The type of register on which the passed value is stored (FPU registers or general purpose registers or others). A certain format specifier will pick up the first argument in the register it encounters first.
If the character is something which is not matched say k
then it may simply print %k
as the string, or do whatever the function implements.
EDIT
Have a look at Mat's answer for the C99 standard specification about the matter.
由于您似乎对实际发生的事情感兴趣,而不是作为最佳实践应该做什么,我将解决这个问题,让其他人引用章节和经文。:-)
格式字符串是一个“提示”,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
,如果您自己计算它们,您会发现它们完全符合您的预期。
但第二个printf
将x
其视为 4 个字符的字符串。由于我的机器是 little-endian 它颠倒了字节顺序,所以它打印对应于 ASCII 72、73、13、10 的字符,它们是
H
I
CR
LF
当然,正如 Mat 所指出的,这有助于理解 背后的机制printf
,但您不应该编写依赖于这种行为的代码。至少,它不是可移植的(例如,大端机器不会更改字节顺序)。