嵌入式培训之C语言学习(十三)预处理命令与指针(1)

一、预处理命令

(一)编译过程

1、预处理

作用:将代码中相关预处理命令执行,最终生成出一个只包含C语言代码的文件;

2、编译

作用:对语法进行检查,将这个c的源代码生成汇编代码;

3、链接

作用:将使用到的其他代码链接到一起,生成最终可执行文件;

4、可执行程序

注:C语言中的预处理功能的最终效果是做文本替换

(二)宏定义

<一>、不带参数的宏定义

1、形式:#define 标识符 表达内容

eg:无脑的文本替换,只换不算(其中PI具有全局作用域

注:末尾不加分号否则编译报错(分号也会被无脑替换(语法错误))

2、写宏左右两边尽量加括号避免优先级高低问题;eg:

输出结果为:63

<二>、带参数的宏定义

1、一般形式:#define  宏名(形参表)  宏的内容

:不需指定数据类型

2、eg(1):#define ADD(a,b)  a+b

                      printf("%d\n",ADD(3,4));//3+4,运行结果为7

                      printf("%d\n",ADD(3,4)*5);//3+4*5,运行结果为23

eg(2):

//3 > 4 + 5(加号优先级高)所以为3 > 9,输出结果为0

eg(3):避免运算优先级高低问题:能加括号的都加括号;

输出结果为6

3、扩:(1)带参宏与函数的实现有本质区别(宏直接展开,函数要保护现场恢复现场);

(2)带参宏是以消耗大量代码区空间来提高执行效率,代码没有复用性。

4、例题:给定三角形三边求三角形面积(用宏)

(三)文件包含

1、一般形式:#include<文件名>   或   #include"文件名''

2、采用绝对路径(包含根目录信息)两种格式没有区别,eg:

#include </home/linux/1.txt>

#include "/home/linux/1.txt"

采用相对路径

#include <1.txt>表示自动在//use/include下寻找文件

#include "1.txt"  表示在当前main.c所在的文件(在同一目录下)寻找

(四)条件编译

1、用法1: #if 0  //0为逻辑结果(非零即为真)

                   #endif

程序代码替换为空白;

2、用法2:#ifdef   标识符(宏)

                              程序段1

                   #else

                               程序段2

                   #endif

若宏定义过则保留程序段1,程序段2被替换为空白;若没定义过宏,则保留程序段2;

3、用法3: #ifndef   标识符(宏)

                    #endif

与用法2的逻辑相反

标准头文件写法

在所有头文件刚开始先加上#ifndef   宏

                                           #define   宏

                                           ......

                                           #endif(加在末尾)

避免对同一个头文件重复包含造成重复定义错误

4、条件编译主要用于调试,eg:此时len输出打印变量被省略

5、条件编译3 用法(标准头文件写法):其保证Clock只被定义一次

二、指针

(一)指针概念

1、指针就是用来装地址的数据类型,地址就是数据在内存单元的编号;

2、当指针为a时,指的是指针变量;当指针为0x1000时,指针指的是地址

(二)定义指针变量

1、通用语法:基类型 *指针变量名

(1)基类型:整型,浮点型,字符型,数据类型,指针类型,结构体类型,函数类型;

     作用:用来表示这个指针类型指向的内存空间存放的是什么类型的数据;

(2)* 定义的时候为类型说明符,表示此时定义的是一个指针类型的变量;

(3)指针变量名,符合标识符命名的规则;

2、eg:

int i = 10;  //i所在的空间是用来存放int类型的数据的

int *p = &i; //此时指针变量p指向了指针变量i(指针变量p保存了变量i的地址)

*p  =  100;//通过指针变量p修改i的值(间接访问);i = 100;为直接访问i空间

&i表示获得i所在空间的首地址;表示获得了一块可以存放int类型的内存空间地址。

3、指针类型:int *p;

(int *)就是指针类型

   int * p 它首先表示的是一个指针类型,然后再表示指向int型数据的指针类型。

4、指针变量的引用

      int i = 10;

      int *p = &i;  //p指向i,因为保存了i的地址(指针变量p保存变量i的地址)

注:在64位系统下所有指针占8个字节(p指针变量地址占8个字节);

       在32位系统下所有指针占4个字节。

5、注意事项

(1)*是指针运算符,也是单目运算符(自左向右),它的运算对象只能是指针(地址);

(2) *p表示访问p所执行的基类型的内存空间;

(3) *p表达式的数据类型与定义指针变量p时出现的基地址类型一定一致

(三)间接访问三大步骤

1、根据指针变量中的值去内存中定位;

2、从定位处开始向后偏移sizeof(基类型)个字节;

3、将偏移后的那部分内存空间当作是一个基类型变量来看。

4、直接访问与间接访问:

(四)扩展

1、指针的指针:下图红色部分为指针的指针

2、指针百分之八十的用途:在函数内部可实现在被调函数中修改主调函数

(1)指针作为函数参数:

         形参—指针类型变量用来接受实参(实参是要操作的内存空间的地址);

         实参—要修改谁,就把谁的地址传过去,要保证空间有效,不能是野指针(保存的地址为随机数,该部分空间不一定被允许写入),eg:

       int  *p;

      *p = 100;

      *p为野指针,编译不报错,运行程序崩溃(断错误)

       注:被调函数中,一定要有*p运算,间接访问操作;

              指针变量(野指针)与指针变量t指向的变量应都是确定的。

(2)值传递:只是实参数据赋值了形参

         地址(指针)传递:传的是地址,可以实现被调修改主调,eg:

        i的输出结果为100。

        注:在创建函数定义形参的时候一定要分清楚哪些是需要值传递,哪些是需要地址(指针)传递。

(五)练习

1、三个数求和

2、求最大值与最小值

3、输出练习:

前3个表达式输出的都是i的地址(*与&可抵消);后2个表达式第一个输出i本身,第二个编译报错。

4、交换两个数的数值

下面的是错误写法:程序运行崩溃(t里是随机数)指针变量t(野指针)与指针变量t指向的变量应都是确定的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值