目录
编译过程
(1)预处理(预编译)(-E):将代码中相关预处理命令执行,最终产生一个只包含C语言代码的文件。
预处理指令: gcc -E file.c -o hello.i
(2)编译(.i)(-S):对语法进行检查,将C的源代码生成汇编代码。
编译指令: gcc -S file.c -o hello.s
(3)汇编(.s)(-c):表示把汇编源代码最终生成机器代码。
汇编指令:gcc -c file.s -o hello.o
(4)链接:将使用到的其它代码链接到一起,生成最终可执行文件。(.out)
(一)预处理
1.宏定义
(1)不带参数的宏定义:
#define 宏名 宏值
(#define 标识符 字符串)
注意:
①预处理命令都是以 # 开头的。
②宏名命名规则和之前标识符命名规则一致。(宏名一般都写成大写,以示区分,小写在语法上也是可以的)
③预处理实际上是将宏名用宏值(预处理阶段的字符串)原样替换(-----文本替换),但是C语言字符串中出现的“宏名”不会被替换。
④应用:a.提高代码可读性;b.一改全改 ----- 方便代码的修改
eg:#define N 10
含义:表示将来代码中出现的 N 都代表10,则编写代码时可以使用N表示数字10。
(2)终止宏定义的命令:
#undef 宏名 \\表示取消宏名的定义
注意:宏名的作用域只是在预处理阶段发挥作用。
作用范围:# define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束;可以用# undef 命令终止宏定义的作用域。
(3)带参宏定义:(宏函数)
#define 宏名(参数) 宏值
eg:#define ADD(a,b) a+b
注意:
带参宏 和 函数 有本质的区别:
a.处理阶段不一样:宏定义----预处理阶段; 函数----编译阶段
b.使用不一样:宏 ----预处理阶段就结束了,宏的使用本质上是文本的原样替换;
函数 ----调用时进行使用,函数的使用本质上是函数代码的调用。
c.参数:宏的参数只是进行文本替换时用的,不进行语法检查;函数的参数是有类型的,编译阶段是要进行类型检查的。
d.应用:一般对于一些短小代码(不超过5行的代码),考虑写成带参宏。
e.宏的副作用:
处理:把能加括号的都加括号
f.宏定义必须写在一行
g.在进行宏定义时,可以引用已定义的宏名,可以层层置换。
2.文件包含
#include <文件名>
#include " 文件名"
<> 和 " " 的区别:
查找头文件的方式不一样:
①<>:表示到系统默认的路径寻找对应的头文件。
② " " :表示到当下目录下寻找头文件,如果没有,再到系统默认路径下寻找。
3.条件编译
(1)语法形式1:
#ifdef 标识符
程序段1
#else
程序段2
#endif
①含义:如果定义了标识符,则预处理程序段1(就是将程序段1的代码保留);否则,预处理程序段2。
②用途:a.调试代码;b.设计头文件
(2)语法形式2:
#ifndef 标识符
程序段1
#else
程序段2
#endif
含义:如果没有定义标识符,则预处理程序段1(就是将程序段1的代码保留);否则,预处理程序段2。
(3)语法形式3:
#if 表达式
程序段1
#else
程序段2
#endif
含义:表达式为真,处理程序段1;表达式为假,处理程序段2。
(二)指针
1.指针的概念
(1)指针就是地址,地址就是内存单元的编号.
(2)指针也是一种数据类型,这种数据类型是专门处理 地址 这种数据类型。
2.定义指针变量
基类型 *指针变量名
(1)基类型:
①整型、浮点型、字符型、数据类型、结构体类型、函数类型
②作用:表示该指针类型所指向的内存空间存放什么类型的数据。
基类型决定了访问空间的大小
(2) * :定义时,表示此时定义的是一个指针类型的变量。
(3)指针变量名:符合标识符命名规则
注意:在 64 位系统上,指针数据类型通常占用 8 个字节的空间来存储地址。
eg: int *p; //pointer
int a = 10; //a所在的空间是用来存放int(整型)类型的数据的
int *p = &a; //p指向了a
&a //表示获得a所在空间的首地址(取地址先取的是编号小的那部分地址)
3.指针类型
int * ----这个整体叫指针类型
含义:首先表示是一个指针类型,表示指向 int 型数据的指针类型
4.指针变量的引用
eg:int *p = &a; //p指向了a ---因为p中保存了a的地址
地址 这种数据类型对应 指针类型。
(1)指针运算:
* ----指针运算符,单目运算,运算对象只能是指针(地址)
eg:*p //表示访问 p 所指向的 基类型 的内存空间 ---间接访问(通过a访问---是直接访问)
访问步骤:①首先拿出p中地址,到内存中定位;
②偏移出 sizeof(基类型) 大小的一块空间;
③将偏移出的这块空间当作基类型变量来看。
*p 的运算效果相当于就是一个基类型的变量。----- *p <=> a