当我在C中定义一个函数并使用它时,我才意识到,我可以稍后使用它并定义该函数,或者稍后定义并使用它。例如,
int mult (int x, int y)
{
return x * y;
}
int main()
{
int x;
int y;
scanf( "%d", &x );
scanf( "%d", &y );
printf( "The product of your two numbers is %d\n", mult( x, y ) );
}
和
int main()
{
int x;
int y;
scanf( "%d", &x );
scanf( "%d", &y );
printf( "The product of your two numbers is %d\n", mult( x, y ) );
}
int mult (int x, int y)
{
return x * y;
}
都可以正常运行。但是,在Python中,第二个代码将失败,因为它需要先定义mult(x,y)
才能使用,并且Python从上到下执行(据我所知)。显然,在C语言中不可能如此,因为第二个脚本运行得很好。那么C代码实际上是如何流动的?
答案 0 :(得分:13)
严格来说,第二个代码不是有效的C。
它使用编译器的灵活性来允许隐式声明函数,而C标准中不允许这样做。
C11
站立的人在“序言”中明确提到了排除,
- 第二版的主要变化包括:
...
- 删除隐式函数声明
您必须要么
在编译器中启用警告,然后编译器应生成一些警告消息,以使您了解此问题。
答案 1 :(得分:1)
正如其他人指出的那样,应该在使用例程之前先声明 ,尽管在使用例程之前不必先定义 。另外,较早的C版本允许进行一些隐式的例程声明,而某些编译器仍然可以这样做,尽管这在很大程度上已经过时了。
关于C如何在定义函数之前就支持它们的调用,首先将C程序翻译成某种可执行格式,然后再执行
在翻译过程中,C编译器读取,分析和处理整个程序。对尚未定义的功能的任何引用都记录为需要在程序中解决的事物。在准备最终的可执行文件的过程中,链接器将遍历所有已处理的数据,查找功能定义,并通过插入被调用例程的地址(或其他信息)来解析引用。
最常见的是,C编译器将源代码转换为对象模块。对象模块包含该程序的机器语言指令。它还包含源代码中定义的程序的任何数据,并且包含有关编译器在分析源代码时发现的未解析引用的信息。多个源文件可以分别转换为多个对象模块。有时,这些翻译是由不同的人在不同的时间完成的。公司可能会产生一个软件库,该软件库是将其源文件转换为目标模块并将其打包为库文件的结果。然后,软件开发人员将编译自己的源文件,并将生成的对象模块与库中的对象模块链接。
可以将多个对象模块链接在一起以创建一个可执行文件。这是操作系统能够加载到内存中并执行的文件。
答案 2 :(得分:0)
对于第二个代码,您应该使用前向声明。这意味着首先声明该函数,以便编译器知道您将使用此函数。目前,您的代码是根据C编译器的灵活性执行的。
Python编译器不够灵活,因此无法编译。
答案 3 :(得分:0)
您说两种代码都可以正常工作。好吧,事实并非如此。第二个代码段将在我的编译器中显示一个错误,如果编译正确,则不应使用。