简体   繁体   English

为什么 main() 后面有 function 定义?

[英]Why there are function definitions after the main()?

I assumed that one of the most used system functions ( ls ) of one of the most famous OSs (linux) written by one of the most authoritative programmers (Richard Stallman) could be an example of really well written code.我认为由最权威的程序员之一(Richard Stallman)编写的最著名的操作系统(linux)之一的最常用的系统函数( ls )可能是编写得非常好的代码的一个例子。

So, being it open source, I decided to have a look at the code (see eg here ).因此,由于它是开源的,我决定看一下代码(参见例如此处)。 There I found several functions defined after the main() , hence after their call, which I expected to be quite uncommon.在那里,我发现了在main()之后定义的几个函数,因此在它们调用之后,我认为这很不常见。

Will any experienced C programmer comment on this?有经验的 C 程序员会对此发表评论吗?

There's absolutely nothing wrong with what Stallman did here.斯托曼在这里所做的绝对没有错。

The C language permits the forward declaration of a function that will be defined afterwards. C 语言允许 function 的前向声明,该声明将在之后定义

This has many advantages, and should not be considered as bad behavior, but rather very good behavior.这有很多好处,不应该被认为是不好的行为,而是非常好的行为。

Advantages (not exhaustive):优点(并非详尽无遗):
- give the programmer a vision of the API exposed by the C code in a quick look, without having to look at all the code - 让程序员快速查看由 C 代码暴露的 API 的愿景,而无需查看所有代码
- permits the use of header files, where you declare a function that will be defined later on in the compilation process. - 允许使用 header 文件,您可以在其中声明function,该文件将在稍后在编译过程中定义 So that you don't have to define your function every time you use it..这样您就不必每次使用它时都定义您的 function ..

In the case of this ls implementation, he simply pre-declared the functions that he'll use in the main() , but if you look carefully, the main function is the first one to appear.在这个ls实现的情况下,他只是预先声明了他将在main()中使用的函数,但如果你仔细观察,主要的 function 是第一个出现的。 This is most probably for the sake of readability, so that you don't have to scroll all the way down to reach the entry point of the program.这很可能是为了便于阅读,这样您就不必一直向下滚动即可到达程序的入口点。

Note that the vocabulary is important here:请注意,词汇在这里很重要:
- function declaration means: just tells the compiler that, somewhere in your code, a function with the same name will be defined. - function 声明意味着:只是告诉编译器,在你的代码的某个地方,将定义一个具有相同名称的 function。
- function definition : the actual function implementation - function 定义:实际的 function 实现

int my_function( char *text); // function declaration, no implementation
int main( int argc, char **argv)
{
   return my_function(argv[0]); // use of the declared function
}

// actual function definition / implementation
int my_function( char *text )
{
   printf("%s\n", text);
}

Edit : after looking more carefully to the code, you can see that Stallman didn't forward-declare all his functions.编辑:在更仔细地查看代码之后,您可以看到 Stallman 没有前向声明他的所有函数。 He has also a rather strange manner of defining functions.他还有一种相当奇怪的定义功能的方式。 I attribute this to the oldness of the code, which is dated of 1985, when the C compiler was not as well defined as today.我将此归因于代码的陈旧性,该代码的日期为 1985 年,当时 C 编译器的定义不如今天。 It must have permitted this kind of function usage before being declared or defined.在声明或定义之前,它必须允许这种 function 使用。

Last but not least, the recent version of ls source code can be found here: http://coreutils.sourcearchive.com/documentation/7.4/ls_8c-source.html ,最后但同样重要的是,最新版本的ls源代码可以在这里找到: http://coreutils.sourcearchive.com/documentation/7.4/ls_8c-source.html
with much more C99-compliant coding than the '85 (Back-to-the-Future) version.与'85(回到未来)版本相比,具有更多符合C99的编码。

In C you usually define function prototypes in header files, then include the header files, so functions can safely be defined after they are called. In C you usually define function prototypes in header files, then include the header files, so functions can safely be defined after they are called.

In the example file you provided the program is sufficiently small that the prototypes are simply put at the top of the file, before the procedure declarations, but the same principle applies.在您提供的示例文件中,程序足够小,原型简单地放在文件顶部,在过程声明之前,但同样的原则适用。

EDIT: Also, that file is pre-K&R C, which is kinda cool but there are some significant differences to modern C, you should not necessarily imitate it.编辑:此外,该文件是 K&R C 之前的文件,这有点酷,但与现代 C 有一些显着差异,您不一定要模仿它。

The code will conceptionally read like a nice specification从概念上讲,该代码将像一个很好的规范一样阅读

  • First define the interface the main entry point uses首先定义主入口点使用的接口
  • Then define the main entry point然后定义主入口点
    • Then the behavior of the program in the ideal case is conceptually fully specified.然后在概念上完全指定理想情况下程序的行为。
  • Last, implement the interface (definitions after main ).最后,实现接口( main之后的定义)。

That he omits declarations of the functions to be put before main (to satisfy first bullet - defining the interface) is considered bad style by many programmers regarding modern C.对于现代 C,许多程序员认为他省略了要放在main之前的函数声明(以满足第一个项目符号 - 定义接口)被认为是不好的风格。

The code however uses old-style function definitions, for which their declarations don't define parameter types to the caller.然而,该代码使用旧式 function 定义,它们的声明没有为调用者定义参数类型。 Presumably, updating this code to be modern C would break a lot of very old systems that still use pre-ANSI compilers.据推测,将此代码更新为现代 C 会破坏许多仍然使用前 ANSI 编译器的非常旧的系统。

For me this is a relic from the pre-prototype era, have a look at newer code and quite often you'll see an inverted code order.对我来说,这是前原型时代的遗物,看看更新的代码,你会经常看到倒置的代码顺序。 The main disadvantage for me is that you have to declare the function on top, and then the function itself way down.对我来说主要的缺点是您必须在顶部声明 function,然后再声明 function 本身。 If you change the function's signature you'll also have to change in 2 locations.如果您更改函数的签名,您还必须在 2 个位置进行更改。 Please note that this is also the case for static functions, a feature that was not used in this piece of code at all... Sure the thing will compile if you don't but you'll get bitten by C's implicit declarations earlier or later.请注意,这也是 static 函数的情况,这段代码中根本没有使用这个特性......如果你不这样做,肯定会编译,但你会被 C 的隐式声明更早或之后。

Seriously, find yourself some more recent code than some oldskool K&R style C, the C language has evolved considerably since then, you might pick up a couple of bad habits in the process.说真的,发现自己比一些 oldskool K&R 风格的 C 更新的代码,C 语言从那时起有了很大的发展,你可能会在这个过程中养成几个坏习惯。

You need to have a prototype in scope before calling the function.在调用 function 之前,您需要在 scope 中有一个原型。 A function definition serves as prototype function 定义用作原型

/* this is a definition and a prototype */
int fx1(void) {
    return 42;
}

/* this is only a prototype */
int fx2(int, const char*);

int main(void) {
    fx1(); /* ok, prototype in scope */
    fx2(42, "foobar"); /* ok, prototype in scope */
}

/* fx2 definition.
** it is undefined behaviour if the prototype here
** does not match the previous prototype */
int fx2(int k, const char *t) {
    return strlen(t) - k;
}

Often, prototypes are declared in header files, which are included at the top of implementation files, before any code.通常,原型在 header 文件中声明,这些文件包含在实现文件的顶部,在任何代码之前。

#include "prototypes.h"
/* define functions in any order: prototypes are all in scope */

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将函数定义放在main()之后是否比将它们放在main()之前有任何优势? - Does putting function definitions after main() have any advantage over placing them before main()? 包含数组定义的代码在主要功能中工作得很好,但是当我从单独的文件中包含它时,为什么不能呢? - Code containing array definitions working great in main function, but not when I include it from a separate file, why? 包括main中.c文件中存在的函数定义 - include function definitions present in .c files in main 如果在 main() 之后定义的函数中没有返回值,为什么 C 中不需要函数原型? - Why is a function prototype not needed in C if there is no return in a function defined after main()? 为什么 function 定义在 C 中隐式外部? - Why are function definitions implicitly external in C? C编译器如何处理不同的主要函数定义? - How does the C compiler handles different main function definitions? 为什么我这个地址在主 function 初始化后被更改? (C) - Why I this address is being changed after initialization in main function? (C) 为什么编译器不从函数定义中推断出函数原型? - Why doesn't the compiler infer function prototypes from function definitions? 为什么我可以使用相同名称的冲突函数原型和定义? - Why can I have conflicting function prototypes and definitions with the same name? 为什么函数指针定义可以使用任意数量的与符号“&”或星号“*”? - Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM