预处理命令
再学习预处理前先回忆一下编程流程:
1.编辑
2.编译
3.运行
4.调试
编译过程:
1.预处理//预编译 ---将代码中相关预处理命令执行,最终产生一个只包含c语言代码的文件
2.编译// --- 对语法进行检查,将这个c的源代码生成汇编代码
3.汇编// --- 将汇编源代码最终生成机器代码
4.链接// --- 将使用到的其它代码链接到一起,最终生成可执行文件
预处理:本质是做文本的替换
宏定义
语法:
#define 标识符 字符串
#define 宏名 宏值
注意:
1.预处理命令都是以#开头的
2.宏名的命名规则和之前的标识符命名规则一致
3.宏名一般都写大写,以区别于普通变量名
4.预处理实际上是将宏名用宏值(预处理阶段的字符串)原样替换(文本替换)
注意:c语言字符串中出现的“宏名”不会被替换
5.应用
a.提高代码可读性
b.一改全改,方便代码修改
6.宏名的作用域
#include<stdio.h>
#define PI 3.14
int main(void)
{
float l,s,r;
scanf("%f",&r);
l = 2 * PI * r;
s = PI * r * r;
printf("l = %g\n",l);
printf("s = %g\n",s);
return 0;
}
# 5 "main.c"
int main(void)
{
float l,s,r;
scanf("%f",&r);
l = 2 * 3.14 * r;
s = 3.14 * r * r;
printf("l = %g\n",l);
printf("s = %g\n",s);
return 0;
}
从该例子可以看出宏值是原样替换
#undef 宏名
表示取消宏名的定义
注意:只是在预处理阶段发挥作用
作业范围:从定义处开始,到#undef结束
eg:
#define n 10
含义:表示将来代码中出现的n都代表10
1.带参宏定义:
语法:
#define 宏名(参数) 宏值
eg
#define ADD(a,b) a+b
注意:
1.带参宏和函数有本质的区别
a.处理阶段不一样
宏定义 -- 预处理阶段
函数 -- 编译阶段
b.使用不一样
宏 -- 预处理阶段就使用结束
宏的所以,本质上是文本的原样替换
宏的参数只是进行文本替换用,不进行语法检查
函数 -- 调用时进行所以
函数的使用,本质上是函数代码的调用
函数的参数,是有类型的,编译阶段要进行类型检查
c.应用
一般对于一些短小的代码,考虑写成带参宏
不超过5行的代码
d.宏的副作用
处理:把能加括号的地方都加括号
e.宏定义必须写在一行 续航符'\'
2.文件包含
#include<文件名>
#include"文件名"
<>与""
区别:查找头文件方式不一样
<> 到系统默认的路径寻找对应的头文件
"" 表示先到当下目录下寻找头文件,如果没有,再到系统默认路径下寻找
3.条件编译
(1)
#ifdef 标识符
程序段1
#else
程序段2
#endif
含义:如果定义了标识符则预处理程序段1
否则处理程序段2
(2)
#ifndef 标识符
程序段1
#else
程序段2
#endif
含义:如果没有定义标识符则预处理程序段1
否则处理程序段2
(3)
#if 表达式
程序段1
#else
程序段2
#endif
含义:表达式为真,处理程序段1;表达式为假,处理程序段2
用途:1.调试代码
2.设计头文件
指针
指针学习过程分三个阶段:
指针基础
指针概念
指针变量定义及引用
指针传参
指针进阶
指针+一维整型数组
指针+一维字符型数组
指针高级用法
指针+二维整形数组
指针+二维字符型数组
指针的数组
指针+函数
指针+指针
今天主要学习指针基础
指针基础
1.指针概念:
地址:内存单元的编号
1.指针就是地址
2.指针也是一种数据类型--指针类型
这种数据类型是专门用来处理地址这种数据
2.指针变量
语法:
基类型 *变量名
(1)基类型--数据类型
作用:表示该指针类型所指向的内存空间存放什么类型的数据
(2)*
定义时表示此时定义的是一个指针类型的变量
(3)指针变量名
符合标识符命名规则
eg:
int * p;
int a = 10; //a所在的空间存放的数据为int型
*p = &a;
&a //表示获得a所在空间的首地址
指针类型
int * ---整体叫指针类型
含义:表示是一个指向int型数据的指针类型
3.指针变量的引用
int a=10;
int *p=&a; //p指向a,因为p中保存了a的地址
* --指针运算符,单目运算,运算对象为指针(地址)
*p //表示访问p所指向的基类型的内存空间
*p //间接访问
step1:首先拿出p中地址,到内存中定位
step2:偏移出sizeof(基类型)大小的一块空间
step3:将偏移出的这块空间,当做一个基类型的变量来看
运算效果相当于一个基类型的变量
a //直接访问