嵌入式学习(十)--C语言(第七章)(指针)

指针


目录

一、指针特点

二、指针概念

        1. 地址

        2. 指针

        3. 指针变量

三、 指针相关运算符

        1. &:

        2. *:

四、指针变量的定义

        1. 定义方法

        2. 野指针

        3. 空指针

        4. 指针特性(变量访问的两种形式)

                1)直接访问

                2)间接访问

五、指针的算术运算

        1. 指针运算符

        2. 不同指针之间的区别

六、指针常见操作

七、指针作为函数参数

        1. 值传递

        2. 地址传递

八、指针和数组的关系

        1. 数组和指针的关系

        2. 数组的本质

        3. 数组作为函数参数

        4. 字符型数组机字符串的传递

                1)字符串传参

                2)字符串的遍历

九、const 指针

        1. const 指针形式

十、指针函数和函数指针

        1. 指针函数

        2. 函数指针

十一、二级指针

        1. 定义

        2. 使用场景

十二、指针数组和数组指针

        1. 定义

        2. 指针数组

        3. 利用指针数组操作二维数组中的字符串实现排序

        4. 数组指针

        5. 数组指针的使用场景

                1)一维数组和指针的关系:

                2)二维数组和指针的关系:

        6. 二维数组的传参

        7. 指针数组的传参

十三、void *指针


一、指针特点

        ○  让代码更加简洁高效

        ○  提供直接访问内存操作

        ○  利用指针可以直接操作硬件

二、指针概念

        1. 地址

                ●  为了区分内存中不同字节的编号(寻址范围:0 - 2^{64} -1

        2. 指针

                ●  指针就是地址,地址就是指针,指针比地址多了指向的概念

        3. 指针变量

                ●  存放指针(地址)的变量称为指针变量(64位操作系统中所有指针变量均为8个字                          节)

三、 指针相关运算符

        1. &:

                ●  取地址运算符,获得变量在内存空间中的首地址      

                        ■  只有变量(左值)才能&,常量和表达式不能进行&操作

                        ■  &构成的表达式值为:变量在内存空间中的首地址

 int Num = 0;
 &Num:得到Num在内存空间中4字节空间的首地址

                        ■  &构成的表达式类型位:变量的类型升级后的类型

int Num;
&Num: int -> int *

        2. *:

                ●  获得指针指向的空间,或者对应空间中的值

                        ■  * 运算符连接的内容必须为指针类型,不能是普通变量类型

                        ■  如果直接使用 * 对应的表达式,表达式值为:该指针指向空间中的值

*&Num;             //获得&Num指向的空间中int类型的值

                        ■  如果使用 * 对应的表达式其类型为:指针类型降级后的类型

//int * -> int 
int *p;
*p;         

                        ■  * 对应的表达式作为左值表示,将等号右边的值放入指针指向的空间

四、指针变量的定义

        1. 定义方法

存储类型 数据类型 *变量名;

int *p;
char *p;
float *p;
double *p;
int *p, *q;

        注意:不能操作未经初始化的指针(野指针)

        2. 野指针

                ●  未经初始化的指针或者指向已经被释放空间的指针,称为野指针

        3. 空指针

                ●  指向内存地址为0x0的指针称为空指针,用NULL来表示

                ●  内存地址0x0空间为只读空间,不能赋值,NULL指针不能执行*p = value操作

int *p = NULL;
int *q = NULL;

int *p, *q;

        4. 指针特性(变量访问的两种形式)

                1)直接访问

                        ■  通过变量的变量名访问变量空间

                2)间接访问

                        ■  通过变量在内存中的地址访问变量空间                        

int num = 0;
int *p = NULL;

p = #
*p;             //间接访问
num;            //直接访问

五、指针的算术运算

        1. 指针运算符

                ●  指针偏移的大小由指针指向的数据类型大小决定

                ●  两个指针相减得到的结果为,两个地址间相差的数据类型元素个数

                ●  +、-、++、--

        2. 不同指针之间的区别

                ●  * 操作时处理方式不同

char *               //取0x2000开始的1个字节空间数据
int *                //取0x2000开始的4个字节空间数据
float *              //取0x2000开始的4个字节空间数据
double *             //取0x2000开始的8个字节空间数据

                ●  算数运算

char *               //偏移量为1个字节
int *                //偏移量为4个字节
float *              //偏移量为4个字节
double *             //偏移量为8个字节

六、指针常见操作

        ○  指针有两个需要注意的概念:指针变量本身,指针指向的空间

        ○  对指针变量:p 或者 q 修改,改变的是指针的指向

        ○  对 *p 或者 *q 操作,改变的是指针指向的空间,指针还是指向原有的空间

int a = 100;
int b = 200;
int *p = NULL;
int *q = NULL;

p = &a;
q = &b;

q = &a;                 //让指针q指向a                 
*q = a;                 //将a的值赋值给q指向的空间,q本身没有改变                  
*p = *q;                //将q指针指向的空间中的值,赋值给p指针指向的空间                
p = q;                  //将指针变量q中的值赋值给指针变量p

七、指针作为函数参数

        1. 值传递

                ●  实参将值传递给形参,形参的值改变,实参不会改变

                ●  函数体内部想使用函数体外部变量值的时候,使用值传递

        2. 地址传递

                ●  实参将地址传递给形参,形参是指向实参的指针,可以利用形参修改实参的值

                ●  函数体内部想修改函数体外部变量值的时候,使用地址传递

八、指针和数组的关系

        1. 数组和指针的关系

                ●  数组的数组名是指向数组第一个元素的指针常量

                ●  数组的数组名 a 可以理解为 int * 型

                注意:两种特殊情况 a 不能理解为 int  *

                        ■  sizeof:sizeof(a) == 20 sizeof(int *) == 8

                        ■  &: &a == int (*)[5] &int * == int **

int a[5] = {1, 2, 3, 4, 5};
int *p = NULL;

p = a;
p = &a[0];
//a == &a[0]

//访问下标为n的元素
a[n] == *(a+n) == *(p+n) == p[n]

        2. 数组的本质

                ●  如:int a[5];

                        ■  开辟20个字节空间,常量 a 表示空间首地址

                        ■  当访问 a[i] 元素时,等价于 *(a+i),能操作对应的空间

        3. 数组作为函数参数

                ●  三种传递形式:

int fun(int a[5]);
int fun(int a[], int len);
int fun(int *parray, int len);

        4. 字符型数组机字符串的传递

                1)字符串传参
int fun(char *pstr);
                2)字符串的遍历
while (*pstr != '\0')
{
    pstr++;
}

九、const 指针

        1. const 指针形式

const int *p;
int const *p;
int *const p;
const int *const p;
int const *const p;

                ●  第一种和第二种形式等价(const修饰 *p)

                        ■  指针变量 p 的值可以改变,但是不能利用p修改指向空间中的值

                ●  第三种(const修饰 p)

                        ■  指针变量 p 的值不能变,但可以利用指针 p 修改指向空间中的值

                        ■  注意指针变量 p 必须初始化,否则后续无法赋值

                ●  第四种和第五种等价(const修饰 *p,const修饰 p)

                        ■  指针变量 p 的值不能变,也不能通过 p 修改指向空间中的值

                        ■  注意指针变量 p 必须初始化,否则后续无法赋值

十、指针函数和函数指针

        1. 指针函数

                ●  是函数,函数的返回值是指针

                        ■  不能返回局部变量的地址

                        ■  指针函数返回的地址可以作为下一个函数调用的参数

        2. 函数指针

                ●  是指针,指针指向一个函数

十一、二级指针

        1. 定义

                ●  二级指针是指向一级指针变量的指针

/*
定义一个指针变量q,占8个字节空间,指向一个指针变量空间,即指向一级指针变量的指针,也就是
二级指针
*/
int **q;

        2. 使用场景

                ●  函数体内部想修改函数体外部指针变量值的时候,需要传指针变量的地址即二级指针

                ●  指针数组传参,数组的数组名是指向数组第一个元素的指针,第一个元素是指针,所                       以数组名为指向指针的指针即二级指针

十二、指针数组和数组指针

        1. 定义

                ●  指针数组:是数组,数组的每个元素是指针

                ●  数组指针:数指针,指针指向整个数组

int *a[5];
//定义一个数组,占40个字节,数组名为a,数组中每个元素都是int *型的指针

int (*a)[5];
//定义一个指针,占8个字节,指针变量名为a,是指向数组20个字节空间的指针

        2. 指针数组

char *pstr[5];

                ●  存放字符串使用字符型数组,操作字符串使用指针

                ●  存放字符串数组使用字符型二维数组,操作字符串数组使用指针数组

        3. 利用指针数组操作二维数组中的字符串实现排序

                ●  二维数组存放字符串数组

                ●  指针数组元素变化代替二维数组字符串变化,提高程序效率

        4. 数组指针

                ●  对一维数组数组名&:值不变,类型升级为指向整个数组的指针

                ●  对指针数组 *:值不变,类型降级为指向数组第一个元素的指针

int a[5] = {1, 2, 3, 4, 5};

a == &a[0]
a == int *

                注意:两种特殊情况 a 不能理解为 int  *

                ●  sizeof:获得数据类型、变量所占字节

                ●  &: & int * -> int ** &a -> int (*p)[5]

        5. 数组指针的使用场景

                1)一维数组和指针的关系:

                        ■  数组的数组名是指向数组第一个元素的指针常量

int a[5] = {1, 2, 3, 4, 5};
int *p = NULL;

p = &a[0];
p = a;
//a == &a[0]

a[n] == *(a+n) == *(p+n) == p[n]
                2)二维数组和指针的关系:

                        ■  数组的数组名是指向数组第一行元素的数组指针

int a[2][3] = {1, 2, 3, 4, 5, 6};
int *p = NULL;
int (*q)[3] = NULL;

p = &a[0][0];
p = a[0];
p = *a;
q = a;

a:指向数组第一行元素的数组指针      int (*)[3]
a[0]:指向a[0][0]的指针             int *
a[1]:指向a[1][0]的指针             int *

访问数组第m行第n列元素的方式:
a[m][n]
*(a[m]+n)
*(*(a+m)+n)
*(p+m*N+n)
*(*(q+m)+n)
*(q[m]+n)
q[m][n]

        6. 二维数组的传参

int a[2][3] = {1, 2, 3, 4, 5};

int fun(int (*p)[3], int len);

        7. 指针数组的传参

char *pstr[5] = {NULL};

int fun(char **ppstr, int len);

十三、void *指针

        ○  void * 指针主要用来保存内存地址

        ○  void* 转换为 char *、int *、double * 类型时,不需要类型转换,直接赋值就行

        ○  char *、int *、double * 转换为 void * 类型时,需要强制类型转换

        ○  void *多用于函数参数和返回值,统一参数和返回值类型

void *p;

char *a;
int *b;
double *c;

p = (void *)a;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值