23 c c++ gcc compiler-errors function
我注意到C++在使用它们之前声明函数签名比C更具限制性,即使函数定义是在实际调用函数之后声明的吗?
我一直认为C更具限制性,但似乎并非如此.
为什么在制定C++编程语言标准时改变了理念?
例如,以下代码运行时编译精细gcc命令,但在尝试编译时输出错误g++
#include<stdio.h>
int main()
{
int a=sum(4,6);
printf("%d",a);
return 0;
}
int sum(int a,int b)
{
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
错误是
‘sum’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
usr*_*usr 23
在旧的(在C99之前)C标准中,有一个称为"隐式函数声明"的东西,自C99以来已被删除.因此,如果您在C90模式下编译,编译器必须支持该"功能".而在C++中,"隐式函数声明"从未出现过.所以GCC出错了.您的代码在现代C(C99或更高版本)中也无效.
使用更严格的编译器开关(例如-std=c99 -Wall -Wextra -pedantic-errors)进行编译,并注意所有诊断.
zwo*_*wol 16
我一直认为C更具限制性,但似乎并非如此.
你落后了.在几乎所有C++ 不是 C 的超集的地方,都是因为C++更具限制性.C++类型系统比C类型系统更严格,删除了你所绊倒的遗留功能("隐式声明"),还有更多保留字等.
确实,C++具有比C 更多的功能,但是您不能混淆语言所具有的功能数量以及缺少限制.ML/Haskell语言系列的设计理念的一个主要方面是提供许多很多功能,但也有很多很多的严格要求.
Lun*_*din 12
C最初允许在没有定义的情况下从程序中调用函数,允许它们"稍后定义".然后,如果你没有定义函数,编译器只需编写一个调用约定,例如"好吧我不知道这个函数返回什么,所以让我猜它返回int".可以对参数进行类似的假设...您可以选择为其定义类型.旧的"K&R风格"C功能看起来像
int func (a, b)
int a;
int b;
{
...
}
Run Code Online (Sandbox Code Playgroud)
要强制参数类型,您必须使用所谓的"原型格式",并使用前向声明,如:
int func (int a, int b); // function prototype since the parameter types are explicit
Run Code Online (Sandbox Code Playgroud)
所有隐含的函数声明行为都是明显危险的废话并导致致命的错误.然而,这种危险的行为在1990年的标准化过程中才被部分淘汰.如果没有原型可见,编译器仍然允许对函数做出隐式假设.(例如,这就是为什么如果你忘了包含stdlib.h,malloc就会完全搞砸了.)
这就是你的代码编译的原因,你使用的是旧版本的gcc(4.x或更旧版本),默认-std=gnu90使用的是1990年的C标准+非标准扩展.较新版本的gcc,5.0或更高版本,默认为-std=gnu11当前的C标准(C11)+非标准扩展.
C++从未允许过这种行为,并且C也修复了它,在1999年使用了C99标准.即使你有一个旧的gcc编译器,你也应该可以编译gcc -std=c99 -pedantic-errors,这意味着"实际上遵循C标准,1999年版本".如果在调用函数之前没有看到正确的函数声明/定义,则会出现编译器错误.