该printf
函数的原型是
int printf(const char * restrict format, ...);
第一个参数始终是描述输出格式的文本字符串(因此你不能只写printf(fruit);
)。...
表示可以在格式字符串之后使用printf
零个或多个附加参数(这称为可变参数函数)。
不幸的是,可变参数函数不会自动知道在参数列表的可变部分中传递给它们的参数的数量或类型。他们只是在最后一个固定参数之后看到下一个可用参数的起始地址。您必须以某种方式将该信息作为固定参数的一部分传递。使用printf
,附加参数的数量和类型由格式字符串中的转换说明符指示。所以当你写
printf("%f\n", fruit);
转换说明符%f
告诉格式字符串后面printf
还有一个类型的附加参数。double
转换说明符还告诉printf
如何格式化值以进行显示。例如,在
printf("%7.2f\n", fruit);
转换说明符%7.2f
告诉printf
将值显示为 7 个字符宽的字段,小数点后有 2 位数字,或9999.99
.
如果参数的类型与转换说明符不匹配,则行为未定义。例如,如果你写
printf("%d\n", fruit);
当您真正传递 a 时,您会告诉printf
期望a ,这是一个逻辑错误。根据底层架构,可能会发生许多不同的事情,因此行为未定义,编译器不必对此做任何特别的事情;任何结果都被认为是“正确的”。真正好的编译器会发出参数与转换说明符不匹配的诊断。大多数人会简单地按原样翻译代码,结果可能是从意外输出到访问冲突的任何结果。 int
double
同样,如果您没有传递足够的参数来匹配转换说明符的数量,则行为未定义:
printf("%f %d\n", fruit);
如果您传递的参数多于转换说明符,则会评估其他参数,否则会被忽略:
printf("%f\n", fruit, apples, bananas);