test.c(源文件)->编译->test.obj(目标文件)->链接->test.exe(可执行文件)
编译
1.预编译(预处理):text.c->text.i
使用gcc -E test.c 进行停止
预处理指令:头文件包含,宏定义的替换和删除
注释删除
2.编译:text.i->text.s
使用 gcc -S test.c 停止
将c语言代码翻译成汇编代码(语法分析 词法分析 语义分析 符号汇总)
符号汇总将全局变量名 函数名 main等符号汇总
3.汇编: test.s->test.o(目标文件elf格式)
使用 gcc -c test.c 停止
1.形成符号表(在符号汇总基础上,符号表上保存符号及其地址)
2.把汇编指令变成二进制指令
链接
合并段表(将多个目标文件对应的位置的数据合并)
符号表的合并和重定义(将符号对应有效的地址保留,无效地址去掉)
程序运行环境
程序载入内存
程序执行
执行程序代码
终止程序
预处理详解
1.预处理符号
_FIFE_ :文件路径
_TIME_ :编译时间
printf("%s",_FIFE_);
2.预处理指令:#define #include #pragma
预处理指令后面不要加分号
#define :定义宏
#define square(x) x^x//宏带的参数可以在后面使用
宏的参数可以有#define 定义的符号
#define a 10
#define add a+2
宏不能递归,字符串中的符号不会被定义
#:在字符串中插入宏的参数
利用字符串有自动连接的特点
#define PRINT(X) printf("the value of"#x"is %d"\n",x)
#define print(format,x) printf("the value of "x" is "format"",x)
//宏中的参数是字符串时不用#,只用""标出,如果不是字符串还要加上#
##:连接两边的符号放在一起
#define add(x,y) x##y//等于xy字符
11##22//1122
#undef 移除一个宏定义
#undef 宏名
宏比较函数的优势和缺点
规模更小,速度更快,节省函数调用,函数返回的时间。
宏的参数无类型(怎么和python好像)
宏的参数可以是类型(int, long )。(面向对象?)
缺点:
宏无法调试。
宏无法递归。
3.宏是直接替换的,影响代码长度。
4.操作符优先级问题。
命名:宏全部大写,函数名不要全部大写
命令行定义:在代码编译的时候,给某些变量赋值
条件编译:选择性编译(和if相似但作用阶段不同)
#ifdef PRINT//如果PRINT被定义则代码编译,否则在预处理阶段就删掉
#ifndef PRINT//如果PRINT不被定义则代码编译,否则在预处理阶段就删掉
printf("1");
#endif
和c中的if语句相似:
#if ex1
#elif ex2
#else
#endlif
嵌套编译指令:#if嵌套#if
文件包含
自定义头文件
#include "wenjian.h"
库文件
#include <stdio.h>
""先在源文件目录下查找头文件,没找到就在库函数文件找到
<>直接在标准路径查找
头文件被包含多少次,预编译时就会出现多少次
防止头文件出现多次
#ifndef _TEST_H_
#define _TEST_H_
//contect
#endif
#pragma once