为什么我可以在C中调用函数而不在C++中声明但不在C++中?

ayu*_*ver 5 c c++

在C++中,在声明函数之前调用函数是一个编译器错误.但在C语言中,它可能会编译.

#include<stdio.h>
int main()
{
   foo(); // foo() is called before its declaration/definition
} 

int foo()
{
   printf("Hello");
   return 0; 
} 
Run Code Online (Sandbox Code Playgroud)

我已经尝试过并且知道它是正确的,但我无法理解它背后的原因.任何人都可以解释编译过程是如何实际发生的,并且两种语言都有所不同.

Iha*_*imi 12

代码" 编译 "为程序的事实并不意味着你可以做到.编译器应该警告函数的隐式声明foo().

在这种特殊情况下,隐式声明会声明相同,foo()并且不会发生任何不良事件.

但假设有以下情况,请说明这一点

main.c中

/* Don't include any header, why would you include it if you don't
   need prototypes? */

int main(void)
{
    printf("%d\n", foo()); // Use "%d" because the compiler will
                           // implicitly declare `foo()` as
                           //
                           //              int foo()
                           //
                           // Using the "correct" specifier, would
                           // invoke undefined behavior "too".
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在假设foo()在另一个编译单元1 foo.c中定义为

foo.c的

double foo()
{
    return 3.5;
}
Run Code Online (Sandbox Code Playgroud)

它按预期工作吗?

您可以想象如果您在malloc()不使用stdio.h的情况下使用会发生什么,这与我上面尝试解释的情况非常相似.

因此,执行此操作将调用未定义的行为2,因此术语" Works "在这种情况下不适用于可理解的意义.

这可以编译的原因是因为在过去很久以前它被标准所允许,即标准.

标准从来不允许这样,所以你不能编译如果你调用一个没有原型("一个功能程序申报代码"),它被称为前.

现代编译器警告这一点,因为可能容易发生未定义的行为,并且由于忘记添加原型或包含适当的头并不难,如果编译器可以对此进行警告而不是突然间有一个非常难以理解的bug.


1 它不能在同一个文件中编译,因为它将使用不同的返回类型定义,因为它已经被隐式声明

2 与事实出发double,并int有不同的类型,会有不确定的,因为这种行为.

  • 由于问题是关于C与C++的行为,你可以提到它在标准C++中从未被允许过. (2认同)

H. *_*ijt 5

在开发C时,函数名称就是您需要能够调用它的全部名称.函数参数的匹配参数完全是程序员的业务; 编译器并不关心你是否将三个浮点数传递给只需一个整数的东西.

然而,事实证明这很容易出错,因此后来C语言的迭代添加了函数原型作为(仍然是可选的)附加限制.在C++中,这些限制已经进一步加强:现在函数原型总是强制性的.

我们可以推测为什么,但部分原因是因为在C++中仅仅知道函数名称已经不够了.可以有多个具有相同名称但具有不同参数的函数,编译器必须确定要调用哪个函数.它还必须弄清楚如何调用(直接或虚拟?),甚至可能必须在模板函数的情况下生成代码.

鉴于我认为语言要求在调用函数时知道函数原型是有意义的.