玳瑁的嵌入式日记D14-0807(C语言)
二级指针
定义个数组
char* str[10]; //表示定义了一个包含 10个 char*类型 数组
char* str[10] = { "hello","world","china"};
此时数组的元素类型 --- 指针类型 --- 指针类型的数组
--- 指针数组 --- 目的处理多个指针
此时 这是一个 指针类型的数组 --- 首元素的地址 str[0] //元素类型 char *
&str[0] //地址类型 char* *
二级指针
char * *p; //如果要保存的是 一个 一级指针变量所在空间的的地址
&p //p所在空间的数据类型 char**
//char***
int a = 10; //整型变量 对应要开要给4字节空间 有空间 就有地址
int * p = &a; //p也是变量(一级指针变量) 是变量 就有空间 有空间 就有地址
int* * q = &p; //q也是变量(二级指针变量) 是变量 就有空间 有空间 就有地址
int** *r = &q; //三级指针
----------------------------------------------------------------
r //r中放的是 q的地址
*r //就相当于是q q中放的就是 p的地址
**r //*q 相当于p p中放的是 a 的地址
***r //*p 相当于a 就是a中的值 10
小结:
想要保存一个【普通变量】的地址 定义一个一级指针
想要保存一个【一级指针变量】的地址 定义二级指针
想要保存一个【二级指针变量】的地址 定义三级指针
... ...
练习:
找出最大值
--------------------------------------------------------------------
练习:
逆序
练习:
排序
比的是字符串
换的是数组中的地址值
练习:
查找
--------------------------------------------------------------------
char s[3][10] = {"hello","world","china"};
char (*p)[10] = s; //p称为 数组指针
--- 指向目标 ---数组类型
char *s[10] = {"hello","world","china"};
//指针数组
char **p = s; //二级指针
数组(的)指针 --- 本质 --- 指针 --- 基类型 是数组类型
指针(的)数组 --- 本质 --- 数组 --- 元素类型 是 指针
---------------------------------------------------------------------
指针 和 函数
//指针(的)函数 --- 本质 ---函数---只是 返回值是指针类型而已
表示 返回值类型 为指针类型的函数
char * strcpy
char * strcat
注意:
1.函数可以返回地址
但是,不能是局部变量(auto--栈上)的地址,auto的局部变量的生命周期 随着函数调用开始存在,函数调用结束销毁
2.局部变量想要返回值地址
static
堆区空间:
特点: 1. 大
2. 手动申请,手动释放
函数
void *malloc(size_t size);
功能:
堆区申请空间
参数:
@size 表示申请的大小
返回值:
成功 返回申请到的堆区空间的地址
失败 NULL
void free(void *ptr);
功能:
释放堆区的空间
参数:
@pstr 之前用malloc申请到的堆区空间的地址
NULL //空指针
void * //空类型指针
//万能指针
// 表示可以接收任意类型的指针
注意:
如果通过 void *类型的地址 进行解引用操作会报错,
如果要用,必须转换为 具体的类型
*p //解引用
:
p //放的是一个地址 --- 引用
*p //解引用
注意:
内存泄露
申请了空间,但是用完后,没有释放
free 不能多次释放
练习:
int a[10];
要求,定义一个数组,放在堆上
输入10个值,输出
函数指针
想通过指针 指向 函数
int add(int a,int b)
{
return a + b;
}
add //函数名 --- 代表的是函数的入口地址
//函数名是标识符
//函数也是一种类型
//去掉标识符 --- 剩下就是标识符对应的数据类型
//int (int a,int b) --- 函数类型 --- 表示是一类函数 ,返回值为int型 ,带有两个int型形参这么一类函数
void *p = add;
int (int a,int b) * p = add; //定义了一个指向 函数 的 指针
-----函数类型---------
int (*p) (int,int) = add; //定义了一个指向 函数 的 指针
add(a,b);
p(a,b)
注意:
函数指针 *运算不起作用
一般不用写 *
直接用指针变量 进行函数调用
p(a,b);
函数回调
main函数的参数:
const char *s[] = {"hello","world","china"};
const char * argv[] //数组 --指针数组 ---const char *
const char ** arg //编译器最终理解的形式
int main(int argc,const char *argv[])
argc 命令行参数的个数
argv 表示命令参数对应字符串的 一个指针数组
考点:
会出现段错,因为char *str的值不能通过*p更改,
值传递的局限性:
getmemory
函数接收的是char*
类型的参数,这是值传递。在函数内部修改p
的值(分配内存)不会影响外部的str
指针,因为函数只得到了str
的副本。野指针操作:
str
始终保持NULL
,调用strcpy(str, "hello")
会尝试向NULL
地址写入数据,导致程序崩溃。
- 方案 1:通过函数返回值将
malloc
分配的地址返回给外部指针(更直观)。 - 方案 2:使用二级指针
char**p
,通过解引用修改外部指针的值(*p = ...
)。