2

我知道总是先执行main()函数,然后函数调用会将程序定向到其他函数。如果*在main ()函数之前调用函数会怎样?他们什么时候被处决?\

我有一个程序(我从网上下载的),在 main() 之前有函数调用。

现在我不知道如果只在 main () 中执行它们(以及在 main 中调用的函数)它们是做什么用的。

这是程序的片段:

static void set_level_indices   (VideoParameters *p_Vid);
static void chroma_mc_setup     (VideoParameters *p_Vid);
static void init_img            (VideoParameters *p_Vid);
static void init_encoder        (VideoParameters *p_Vid, InputParameters *p_Inp);
static int  init_global_buffers (VideoParameters *p_Vid, InputParameters *p_Inp);
static void free_global_buffers (VideoParameters *p_Vid, InputParameters *p_Inp);
static void free_img            (VideoParameters *p_Vid, InputParameters *p_Inp);
static void free_params         (InputParameters *p_Inp);

static void encode_sequence     (VideoParameters *p_Vid, InputParameters *p_Inp);

*(SOME FUNCTION DECLARATIONS OMITTED)*

int main(int argc, char **argv)
{
  init_time();
#if MEMORY_DEBUG
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

  alloc_encoder(&p_Enc);

  Configure (p_Enc->p_Vid, p_Enc->p_Inp, argc, argv);

  // init encoder
  init_encoder(p_Enc->p_Vid, p_Enc->p_Inp);

  // encode sequence
  encode_sequence(p_Enc->p_Vid, p_Enc->p_Inp);

  // terminate sequence
  free_encoder_memory(p_Enc->p_Vid, p_Enc->p_Inp);

  free_params (p_Enc->p_Inp);  
  free_encoder(p_Enc);

  return 0;
}

现在我想到了,静态是否与在 main() 还可以之前完成的这些调用有关?

这是H.264在其参考软件中的编码器。

编辑

上面的代码是main()函数调用、函数原型还是函数声明。你们都给出了不同的答案。请选择一个并通过展示格式来解释原因。我真的以为这些语句是函数调用的形式。此外,函数原型可以包含在源代码中而不是头文件中吗?谢谢!

4

7 回答 7

14

如果您要问这是如何实现的,那不是通过 C 语言的标准特性。

C 运行时通过为操作系统提供一个入口点来工作,以便在您执行二进制文件时执行。该入口点运行特定于编译器实现的代码。它将设置一些初始化代码,然后调用您的main()函数(如果提供了任何命令行参数)。在调用之前执行的 C 运行时本身之外的任何其他代码都是main()C 语言之外的机制(或编译器提供的 C 语言的扩展)。

在 C++ 中,全局构造函数在main().

在 C 中,您的编译器实现可能会提供一个扩展,允许将函数标记为在main()调用之前执行。在 GCC 中,这可以通过constructor属性来完成。

void foo () __attribute__((constructor));
void foo () { puts(__func__); }
int main () { puts(__func__); return 0; }

上述程序的输出(使用 GCC 编译时)为:

foo
main
于 2013-06-29T03:18:08.517 回答
5

在您发布的代码中,函数在 main 之前声明,这并不意味着调用这些函数。它们被声明,通知编译器这些函数将在程序中使用

于 2013-06-29T03:41:13.430 回答
3

在您列出的代码中,前面的函数main是函数原型,也称为函数声明(它们是同义词)。它们不是函数调用。您可以判断它们不是函数调用,原因有两个:

  1. 不能从全局范围调用函数。全局作用域是函数体之外的任何东西。这是识别它的最快方法,但它有点摇摆不定。
  2. 真正的原因是函数调用前面没有类型说明符或类型限定符,例如voidand static。这些关键字指定符号的类型,在这种情况下是声明的函数。函数调用没有类型(返回值有,但调用本身没有),因此您永远不会以这种方式为函数调用指定类型。

要回答您的其他一些问题:

  • 在大多数实现中(并且根据 C 标准),要执行的第一个用户定义函数始终是main,在这种情况下,您不可能编写在 main 之前调用任何其他函数的代码。在大多数情况下,编译器会生成自己的初始化代码,这些代码会在您的 main 函数之前执行。它执行诸如设置内存和初始化静态变量之类的操作。在某些情况下,您可以编写将用作初始化的一部分的代码,但这相对不常见,并且编译器特定如何执行此操作。
  • 函数原型或函数声明只是在实际定义/实现函数之前告诉编译器函数的一种方式。声明/原型(同样的事情)告诉编译器:a)这个符号是一个函数,b)它有这样那样的返回类型,c)它有这样那样的参数列表。这样,当编译器看到您尝试在代码中的其他位置调用该函数时,它就会知道您要做什么。
  • static关键字称为存储说明符。在函数上,它仅仅意味着函数名没有被导出到链接器,因此不能从任何其他代码模块(即,从任何其他 C 源文件)调用它。所以它实际上只是一种限制函数可见性或范围的方法。
  • 请记住,头文件只是在多个位置包含相同内容的一种方式。无论您#include是文件的何处,编译器都会将其视为包含文件的内容直接出现在包含该文件的位置。所以函数原型/声明会经常出现在头文件中。这允许从包含标头的任何源文件中“知道”(并因此调用)该函数。函数实现(也称为函数定义)通常应该放在头文件中。这样做会导致每次包含文件时都定义函数,这通常会导致链接器抱怨(函数的)名称有多个定义。(解决这个问题的唯一方法是标记函数static,然后每次包含标头时,您实际上是在定义一个文件本地函数,而不是实现一个可以从多个源文件调用的具有全局范围的单个函数。后者通常是你想要的。)
于 2013-06-29T04:28:55.097 回答
2

我认为您可能误解了函数声明和函数调用。

#include <stdio.h>
void foo(void);
int main(void)
{
    printf("main\n");
    foo();
    return 0;
}
void foo(void)
{
    printf("func\n");
}

在上面的简单程序中,由于定义在foo下面main,所以必须在前面声明main。要么将声明放在头文件中并包含它,要么将声明放在main调用它们的任何函数之前。

更新

static只是在文件中限制其范围的函数,没有其他含义。

于 2013-06-29T03:20:23.983 回答
1

只需在每个函数中写一个打印语句..

printf(" main");

printf("function 1")ETC

您将获得被调用函数的顺序。默认情况下,主函数总是首先被调用,在执行结束时,主函数应该返回一个 int、float 等,如主定义中所声明的。

于 2013-06-29T06:16:01.833 回答
0

如果在函数之前调用main函数,那么main函数的意义何在?main是大多数语言中编译器的起点。

如果要在函数代码之前运行函数,main()只需在运行任何代码之前调用它。

于 2013-06-29T03:21:04.500 回答
-1

如果函数在主函数之前调用,它们将在主函数之前执行。

于 2013-06-29T03:13:34.367 回答