1、预编译( 生成 hello.i 文件)(宏定义替换等等)(宏定义指令,如 #define a b,条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等, gcc -E x.c -o x.i
头文件包含指令,如#include “FileName”或者#include <FileName>等,特殊符号,预编译程序可以识别一些特殊的符号。)
2、编译(生成汇编代码 hello.s)(生成汇编语言)gcc -S x.i -o x.s
3、汇编(生成hello.o文件)(生成机器语言)gcc -c x.s -o x.o
4、链接(生成可执行程序),某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。gcc x.o -o x
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
宏定义:
宏定义的解析规则就是:在预处理阶段由预处理器进行替换,这个替换是原封不动的替换。
宏可以带参数,称为带参宏。
宏定义时默认是int类型,所以写程序时注意转换类型。
char -128 ~ +127 (1 Byte)
short -32767 ~ + 32768 (2 Bytes) 3*10^4
unsigned short 0 ~ 65536 (2 Bytes) 6*10^4
int -2147483648 ~ +2147483647 (4 Bytes) 2*10^9
unsigned int 0 ~ 4294967295 (4 Bytes) 4*10^9
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes) 9*10^18
double 1.7 * 10^308 (8 Bytes)
加UL后缀,说明时无符号长整型数。
带参宏和带参函数的区别:
宏定义是在预处理阶段处理,而函数是在编译时处理。
宏定义和函数的最大区别:宏定义是原地展开,没有跳转开销,函数长度越长调用开销比例越小。所以函数更长时一般使用函数,函数体很短用宏定义,效率更高。
宏定义不会检查参数的类型,返回值也不会附带类型;而函数有明确的参数类型和返回值类型。
内联函数和inline关键字:
内联函数通过在函数定义前加inline关键字实现,本质上是函数,编译器可以做静态类型检查,但是又同时可以实现原地展开而不需要跳转。所以可以认为,内联函数就是带了参数静态类型检查的宏。当函数内函数体很短(一两句)而又希望编译器进行参数检查,最适合使用内联函数。(使用非常广泛)