我想知道为什么我们需要指定像“%f”这样的数据类型来打印浮点数的“x”变量。 “x”已经是一个浮点数,所以为什么我们需要再次告诉程序我们打印一个浮点数变量。 这可能看起来像一个愚蠢的问题,但我很好奇背后的原因。
float x = 5.0;
printf("%f",x);
答案 0 :(得分:2)
为什么 printf ... 需要指定数据类型(?)
int printf(const char * restrict format, ...);
是一个 variadic function。 printf()
不直接接收超过 format
参数的有关其他传递内容及其类型的信息。
printf()
使用 format
来了解以下 ...
参数的数量、位置和类型。
format 参数有多种鲜为人知的替代方法。 e.g.
答案 1 :(得分:1)
编译器在编译时就知道有关变量类型的信息,但它不像其他语言那样为正在运行的程序保留任何这些信息。在运行时,当调用 printf() 时,您必须提供在编译过程中丢失的类型信息。
他们是否可以编写编译器来使用编译时信息来编译对 printf() 的不同调用?是的。但这会使 printf() 与所有其他函数不同,并且以用户无法为自己编写的方式“神奇”。按照现在的做法,您可以自己编写类似 printf() 的函数。
答案 2 :(得分:1)
它是 C 中可变参数函数如何工作的函数。printf
的原型是
int printf( const char * restrict format, ... );
只有第一个参数 format
是已知的固定类型。任何附加参数都没有固定的顺序或类型。例如,如果你写
printf( "%d %s %f\n", 1, "2", 3.14159 );
编译器通过评估附加参数并将它们的结果压入堆栈或将它们写入特定寄存器来设置函数调用。但是,调用者无法将附加参数的数量或类型传达给 printf
。参数本身没有任何内容可以表明它们的类型或有多少。 printf
只看到堆栈上的一堆字节(或一堆参数寄存器),但它并不神奇地知道如何从中挑选特定项目。
这就是为什么您需要格式字符串中的转换说明符来告诉 printf
期望什么。
答案 3 :(得分:0)
在其他语言中,它通过泛型、继承或多态
来解决泛型类似于 <genericType T> void print(T)
(我没有任何示例)
至于继承,在Java中,你有System.out.println(Object)
函数,它接收任何类型(一切都继承Object
)
每个 Object
都有 toString
方法告诉它要打印什么(如何表示)
最后,我们在 C++ 中看到的多态性
您可以在其中重载 <<
的 std::cout
运算符
喜欢std::ostream& operator<<(std::ostream& os, const Date& dt)
在这种情况下链接器/编译器选择哪个方法(具有相同的名称;标准是/是参数类型)
C 没有(有意)任何这些东西
可能是因为它想保持“简单”(接近,但不要太接近装配)