前言:
现时看官们对“c语言链接过程细节”大约比较注意,你们都想要知道一些“c语言链接过程细节”的相关知识。那么小编在网上收集了一些关于“c语言链接过程细节””的相关资讯,希望朋友们能喜欢,姐妹们一起来学习一下吧!原文首发于同名微信公号「Allen5G」,欢迎大家搜索关注,欢迎转发!
补充一个知识点:
&是一个位运算符,就是将两个二进制的数逐位相与,就是都是1才是1,只要有一个为0则为0,结果是相与之后的结果。
&&是一个逻辑运算符,就是判断两个表达式的真假性,只有两个表达式同时为真才为真,有一个为假则为假,具有短路性质。
编译器基本构成:
C语言编译基本流程图解:
就按照上边的流程一步步介绍下:
预编译:
处理所有的注释,以空格代替
将所有的#define删除,并且展开左右的宏定义
处理条件编译指令#if,#ifdef ,#elif ,#else , #endif
处理#include , 展开被包含的文件
保留编译器需要使用的#pragma指令
例子: gcc - E file.c -o file.i
编译:
~对预处理文件进行词法分析,语法分析和语义分析
语法分析:分析关键字,标识符,立即数等是否合法
语法分析:分析表达式是是否遵循语法规则
语义分析:在语法分析的基础上记忆布分析表达式是否合法
~分析结束后进行代码优化生成相应的汇编文件
编译指令实例: gcc -S file.i -o file.s
汇编:
汇编器将汇编代码转变为机器的可以执行的代码
每条汇编语句几乎都对应一条机器指令
汇编指令实例: gcc -c file.s -o file.o
实验1:源代码单步编译实例
#include "19-1.h"// Begin to define macro#define GREETING "Hello world!"#define INC(x) x++// Endint main(){ p = GREETING; INC(i); return 0;}# 1 "19-1.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "19-1.c"# 1 "19-1.h" 1# 9 "19-1.h"char* p = "Delphi";int i = 0;# 2 "19-1.c" 2# 11 "19-1.c"int main(){ p = "Hello world!"; i++; return 0;} .file "19-1.c" .globl p .section .rodata.LC0: .string "Delphi" .data .align 8 .type p, @object .size p, 8p: .quad .LC0 .globl i .bss .align 4 .type i, @object .size i, 4i: .zero 4 .section .rodata.LC1: .string "Hello world!" .text .globl main .type main, @functionmain:.LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq $.LC1, p(%rip) movl i(%rip), %eax addl $1, %eax movl %eax, i(%rip) movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc.LFE0: .size main, .-main .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609" .section .note.GNU-stack,"",@progbits
.h
/* This is a header file. */char* p = "Delphi";int i = 0;
最后一个:链接
链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接
图解:
静态链接:
由链接器在链接时将库的内容直接加到可执行程序中
linux下静态库的创建和使用
编译静态库源码; gcc -c lib.c -o lib.o生成静态库文件:ar -q lib.a lib.o使用静态库编译:gcc main.c lib.a -o main.out
实验1:静态链接实验 slib.c
#include <stdio.h>extern char* name();extern int add(int a, int b);int main(){ printf("Name: %s\n", name()); printf("Result: %d\n", add(2, 3)); return 0;}
char* name(){ return "Static Lib";}int add(int a, int b){ return a + b;}
动态链接:
可执行程序在运行时才会动态加载库进行链接
库的内容不会进入可执行程序当中
linux下动态库的创建和使用
编译动态库源码:gcc -shared dlib.c -o dlib.so
使用动态库编译:gcc main.c -ldl -o main.out
关键系统调用
dlopen:打开动态库文件
dlsym:查找动态库中的函数并返回调用地址
dlclose:关闭动态库文件
实验2:动态链接实验 dlib.c
#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;}
char* name(){ return "Dynamic Lib";}int add(int a, int b){ return a + b;}
标签: #c语言链接过程细节