您的位置:首页 > 编程语言 > C语言/C++

c语言编译、汇编、链接、执行过程分析

2018-01-05 22:06 281 查看

1、c程序的编译过程一般为:

预处理
编译成汇编代码(生成 .s 文件)
汇编成目标代码(生成 .o 文件)
链接 (生成 .exe)



2、举例分析

        c编译器基本都是以c文件为单位进行编译的,也就是说当编译器在编译某个c文件的时候,编译器并不知道项目中有其他的c文件的存在。c编译器只针对当前正在编译的c文件,它并不知道还有多少个其他的c文件,也不知道这些c文件之间的关系(主要是调用关系)。关于这一点,在之前的博文中有讲过,见:http://blog.csdn.net/baidu_35679960/article/details/66973829

        因此,当某个c文件中引用了(如访问或者是调用)其他c文件中定义的全局变量或者是函数时,编译器并不清楚被引用的全局变量或函数是否真的存在,存在于何处,那么编译器如何解决这个问题呢?对于这种情况,编译器要求被编译的c文件必须采用extern关键字显示的声明这些外部定义的全局变量或函数,告诉编译器这些变量和函数来自于当前被编译的c文件之外。

        对多个c文件在linux下通过gcc编译器进行手动编译链接,而不是在IDE下去操作,能够增深对这一过程的了解,通过这样的方式也有利于学习makefile的书写。具体来说:

1、// 新建文件:add.c,min.c,head.h,main.c,内容如下:

//add.c
int add (int a, int b){
    return a+b;
}

//min.c
int min(int a, int b){
    return a-b;
}

//head.h
extern int add(int a, int b);
extern int min(int a, int b);

//main.c
#include <stdio.h>
#include "head.h"
int main(){
        printf("add result = %d\n", add(2, 3));
        printf("min result = %d\n", min(2, 3));
        return 0;
}

2、将add.c和min.c编译成目标文件
gcc -c add.c -o add.o
gcc -c min.c -o min.o
ps:上面这两条指令可以合并为:gcc -c add.c min.c

3、将main.c链接 .o文件生成可执行文件
gcc main.c add.o min.o -I. -o main
ps:上面这条命令可以进一步拆分为两条指令:
gcc -c main.c -I. -o main.o
gcc main.o add.o min.o -o main

4、执行可执行文件
./main

5、输出:
add result = 5
min result = -1


3、额外说明

c语言中函数应该先声明,再使用,这是推荐的情况,在vc6中也是这么实现的,但是gcc编译器稍有不同,见博文:C语言中,函数不声明也能使用,但会出现warning: implicit declaration of function,在linux的gcc编译器下,自定义函数未经声明却能在主程序中被调用,程序也能正常运行(有warning:implicit declaration of function)。这是因为在C语言中,当函数在调用函数之前没有声明或定义,默认作为隐式声明处理,只要在调用函数之后定义,或在别的模块中定义并编译成库文件,该库文件在调用函数所属模块编译时载入,程序即可正常运行。

        c语言在gcc编译器下自定义函数不声明可以在主函数中使用,但是在c++在g++编译器中不可以,因为g++使用C++的规则:函数在被调用前必须声明或定义。c++语言中一般的操作是:类定义在头文件中,假设为Class.h;类中成员函数的实现定义在源文件中假设为Class.cpp,并且include "Class.h";其他使用类的文件也应该include "Class.h",详见:为什么类的定义应当写在头文件中,从而被多个源文件包含?

参考:

[1] C语言编译原理介绍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐