C进阶:19~20、编译与链接

编译器包括:预处理器、编译器、汇编器、链接器。

file.c + file.h --> 预处理器 ————>file.i --> 编译器 --> file.s --> 汇编器 --> file.o

预编译:

        处理所有的注释,以空格代替;

        将所有的#define删除,并且展开所有的宏定义;

        处理条件编译指令:#if、#ifdef、#elif、#else、#endif;

        处理#include,展开被包含的文件;

        保留编译器需要使用的#pragma。

预处理指令示例:

gcc -E file.c -o file.i

编译:

        对预处理文件进行词法分析、语法分析和语义分析。

                词法分析: 分析关键字,标识符,立即数等是否合法;

                词法分析:分析表达式是否遵循语法分析;

                语义分析:在语法分析的基础上进一步分析表达式是否合法。

        分析结束后进行代码优化生成相应的汇编代码文件。

编译指令示例:

gcc -S file.c -o file.s

汇编:

        汇编器将汇编代码转变为机器的可执行指令;

        每条汇编语句几乎都对应一条机器指令。

汇编指令示例:

gcc -c file.s -o file.o

链接器:

gcc file.o  //生成a.out

链接过程:

工程中的每个C语言源文件被编译后生产目标文件,这些目标文件如何生成最终的可执行程序?

链接器:链接器的主要作用就是把各个模块之间相互作用的部分处理好,使得各个模块之间能够正确的衔接。

静态链接:由链接器在链接时将库的内容直接加入到可执行程序中:   

file1.0 + file2.0 + libc.a   --> 链接器 --> a.out

Linux下静态库的创建和使用:

	编译静态库源码:gcc -c lib.c -o lib.o
	生成静态库文件:ar -1 lib.a lib.o
	使用静态库编译:gcc main.c lib.a -o main.out

动态链接:

        可执行程序在运行时才动态加载库进行链接;

        库的内容不会进入可执行程序中。

lib1.so --> stub1 -->
						链接器linker  --> a.out
lib2.so --> stub2 -->

Linux下动态库的创建和使用:

	编译动态库源码: gcc -shared dlib.c -o dlib.so
	使用动态库编译: gcc main.c -ldl -o main.out          //-ldl 编译选项:使用动态链接的方式

观察下面代码,体会动态库的使用:

        关键系统调用:

	dlopen: 	打开动态库文件
	dlsym:		查找动态库中的函数并返回调用地址
	dlclose:	关闭动态库文件

代码如下:

#include <stdio.h>
#include <dlfcn.h>

int main()
{
    void* pdlib = dlopen("./dlib.so", RTLD_LAZY);

    char* (*pname)();
    int (*padd)(int, int);

    if( pdlib != NULL )
    {
        pname = dlsym(pdlib, "name");
        padd = dlsym(pdlib, "add");
 
        if( (pname != NULL) && (padd != NULL) )
        {
            printf("Name: %s\n", pname());
            printf("Result: %d\n", padd(2, 3));
        }

        dlclose(pdlib);
    }
    else
    {
        printf("Cannot open lib ...\n");
    }

    return 0;
}

删除.so文件后,.out文件将无法执行。

~/will$ gcc -shared dlib.c -o dlib.so
~/will$ gcc test.c -ldl -o main.out
~/will$ ./main.out
Name: Dynamic Lib
Result: 5

小结:链接是指将目标文件最终链接为可执行程序;

        根据链接方式的不同,链接过程可分为:

            静态链接:目标文件直接链接进入可执行程序:(将库整合进一应用程序,适合一部分小程序)

            动态链接:在程序启动后才动态加载目标文件。

猜你喜欢

转载自blog.csdn.net/qq_28388835/article/details/80211515