在main函数之前调用函数,以及对设计的作用

#include <stdio.h>

#include <stdlib.h>

static void before(void) __attribute__ ((constructor));

static void after(void) __attribute__ ((destructor));

static void middle(void);

static void before()

{

        fprintf(stderr, "In %s %d\n", __func__, __LINE__);

}

static void after()

{

        fprintf(stderr, "In %s %d\n", __func__, __LINE__);

}

static void middle()

{

        fprintf(stderr, "In %s %d\n", __func__, __LINE__);

}

int main(void)

{        printf("bengin\n");

        atexit(middle);

        printf("end\n");

        return 0;

}

通过指定

static void before(void) __attribute__ ((constructor));

表明这个函数应该在main之前执行

static void after(void) __attribute__ ((destructor));

表明函数在main之后执行

atexit表明函数在退出的时候执行

执行结果:

In before 10

bengin

end

In middle 20

In after 15

 

一种解释

实际上,在可执行文件被加载之后,控制权立即交给由编译器插入的Start函数,它将对后面这些全局变量进行准备:
   _osver 操作系统的构件编号
      _winmajor 操作系统的主版本号
      _winminor 操作系统的次版本号
      _winver 操作系统完全版本号
      __argc 命令行参数个数
      __argv 指向参数字符串的指针数组
      _environ 指向环境变量字符串的指针数组
Start函数初始化堆并调用main函数.mian函数返回之后,Start函数调用Exit函数结束该进程.
启动函数Start的源代码在:
   crt0.c Microsoft Visual C++

      c0w.asm Borladn C++

 

 二、

 我们看下面的例子:
    
    /* file name test00.c */
    
    int main(int argc, char* argv)
    {
     return 0;
    }
    
    编译链接它:
    cc test00.c -o test.exe
    会生成 test.exe
    
    但是我们加上这个选项: -nostdlib (不链接标准库)
    cc test00.c -nostdlib -o test.exe
    链接器会报错:
    undefined symbol: __start
    
    也就是说:
    1. 编译器缺省是找 __start 符号,而不是 main
    2. __start 这个符号是程序的起始点
    3. main 是被标准库调用的一个符号

 

 

main函数执行之前,主要就是初始化系统相关资源:

1.设置栈指针

2.初始化static静态和global全局变量,即data段的内容

3.将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容

4.运行全局构造器,估计是C++中构造函数之类的吧

5.将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函


你可能感兴趣的:(编译器)