当前位置: 首页 > 知识库问答 >
问题:

为什么在C中编写声明和使用函数的顺序与C相反并不重要

江衡
2023-03-14

我想知道,当我用C#Unity为我的游戏编写代码时,我可以在使用它们之后声明代码中的无效,并且代码仍然有效。另一方面,当我编写纯C代码时,我需要在使用它们之前声明我的函数,我很好奇为什么会出现这种差异?

共有1个答案

陈胤
2023-03-14

我想知道,当我用C#Unity为我的游戏编写代码时,我可以在使用它们之后声明代码中的无效,并且代码仍然有效。另一方面,当我编写纯C代码时,我需要在使用它们之前声明我的函数,我很好奇为什么会出现这种差异?

简短答复:

  • 因为C和C#是完全不同的编程语言,它们有完全独立的背景和编译器。
  • 因为C是在C之上构建的,并且继承了它的编译过程。
  • ... C是在编译器只通过源代码1次,最小的内存使用,这就需要前向声明的时候设计的,而C#是在编译器可以进行“多遍”运行和构建大型内存程序模型的时候设计的这就消除了预先声明的必要性。

详细回答:

请注意,我所说的“多次传递”并不是指编译器实际上从头开始多次重新解析和处理源文件;这意味着,在C#编译器解析源代码(只发生一次)后,它可以提取出程序实际使用的东西(如类型、方法等)的所有符号,并将其存储在内存中的列表中(已用东西列表)只有在建立了程序完全定义的所有内容的列表(list of defined things)并比较了这两个列表后,才会抱怨缺少/损坏的引用。而在20世纪70年代和80年代早期,计算机根本没有足够的内存来存储这些列表,因此C需要它。

现在,在2021年的今天,可以说有可能有一个不需要前向声明的C(甚至是C编译器),但是这是另一个与太多原因有关的话题,我不会深入讨论(尽管主要原因可能是因为根本没有任何需求:所有现有的C和C程序都已经有了前向声明,没有人会仅仅因为一个编译器支持它而编写没有前向声明的C或C程序。国际标准化组织C和C语言设计委员会可以引入它,但是因为前向声明是C语言设计的基础,它将是对更广泛的C和C生态系统的真正巨大的突破性变化,每个人都会抱怨。

C是在C之上构建的,因此它继承了向前声明的要求。与当时的其他OOP语言(如Smalltalk和Object Pascal)相比,C与C源代码的兼容性是C受欢迎的一个巨大的积极因素,后者要求现有的C程序要么完全移植到一种新语言,要么要求C程序以二进制形式链接,这使一切变得复杂。

Objective-C是另一种构建在C之上的OOP语言,它也继承了C对前向声明的要求

可以说,C本来可以设计成无需前向声明就可以编译,但这会增加大量复杂性w.r.t.它与C源文件的兼容性,而且几乎可以肯定的是,推迟C本身的发布日期,因为敲定C兼容编译而无需提前声明的具体工作规范需要几个月甚至几年才能完成。

回顾上世纪90年代中期的Java(最终是C#),这些现代编程语言根本不打算与C程序在源代码上兼容(尽管使用了共享的花括号语法),这意味着这些语言不需要围绕当时硬件限制所施加的限制进行设计。

这并不是说Java语言的人机工程学设计没有受到编译器设计的影响:Java仍然需要每个文件1个类型和CLASSPATH/SOURCEPATH胡说八道。我知道这些限制对于Java当时非常快速和简单的编译器来说是必要的,这确实意味着所有Java项目都将有一个可预测的布局,但25年后,这些限制越来越被视为给程序员带来了一个非常乏味的负担,并且总体上是愚蠢的限制,没有什么好处。然而,与C#、Rust、Kotlin、Go、Swift等后Java语言相比,后者将项目的源代码安排与编译输出完全解耦

我想你已经读过了:C语言中的转发声明是什么如果你没有读过,那么你应该先读一读。

现在,考虑这张表并找出相关性:

 类似资料:
  • 为什么google c/c++风格不允许在多重声明中使用 & 或 * 如上

  • 本文向大家介绍在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?相关面试题,主要包含被问及在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?时的应答技巧和注意事项,需要的朋友参考一下 C++ 语言支持函数重载,C 语言不支持函数重载。函数被C++ 编译后在库中的名字与 C 语言的不同。假设某个函数的原型为:void foo(int x, in

  • 我习惯像这样声明数组内联: 为什么我不能对函数执行相同的操作?假设我有一个类,其中包含and 方法,这是有效的: 但是,这不是: 它不喜欢内联数组声明,编译器错误是“不能创建函数的泛型数组” 编辑 我认为我的问题不是建议的副本,因为我想使用数组初始值设定项语法静态定义一组函数

  • 以下程序失败: 与: 将派生方法设置为受保护/私有作品。 问:Java不允许你进一步限制子类访问的原因是什么?我将其与具有完全相反规则的C进行对比。

  • 问题内容: 改善这个问题 更新 (为清楚起见,以减少歧义): 我将开始修补android应用程序。我打算使用NDK用C 编写C语言(因为我在C 方面有更多的经验,并且喜欢Java),但是在Android NDK页面 上遇到了以下内容: 仅当NDK对您的应用 程序 至关重要时,才应使用NDK- 决不因为您只喜欢使用C / C ++进行编程。 我的印象是,只要适合您的工作,就应该使用自己喜欢的语言。有

  • 问题内容: 原始问题: 当我的JavaScript调用的功能在页面下方而不是在调用页面的下方定义时,JSHint会抱怨。但是,我的页面是用于游戏的,在下载全部内容之前,不会调用任何函数。那么为什么订单功能出现在我的代码中很重要? 我在里面吟。看来我需要花另一天的时间才能重新排序六千行代码。使用javascript的学习曲线一点也不陡峭,但是非常糟糕。 问题答案: tl; dr 如果在加载完成之前不