为什么C++在函数原型(签名)的前向声明方面更具限制性?

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)进行编译,并注意所有诊断.

  • @cmaster否.C标准只要求编译器必须为标准违规提供"诊断消息".C标准中不存在术语"错误"和"警告". (12认同)

zwo*_*wol 16

我一直认为C更具限制性,但似乎并非如此.

你落后了.在几乎所有C++ 不是 C 的超集的地方,都是因为C++更具限制性.C++类型系统比C类型系统更严格,删除了你所绊倒的遗留功能("隐式声明"),还有更多保留字等.

确实,C++具有比C 更多的功能,但是您不能混淆语言所具有的功能数量以及缺少限制.ML/Haskell语言系列的设计理念的一个主要方面是提供许多很多功能,但也有很多很多的严格要求.

  • @JenniferAnderson C肯定更简单(我会把原始作为一种侮辱),但肯定不是"老".两种语言都在积极发展. (4认同)
  • @JenniferAnderson - Noooo.兹沃尔从未暗示过这一点.C不同! (3认同)

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年版本".如果在调用函数之前没有看到正确的函数声明/定义,则会出现编译器错误.