1,指针铁律
1.1,指针是一种数据类型
1, 指针也是一种变量,占有内存空间,用来保存内存地址。
指针既然是变量也要占用内存大小。一级指针的大小于其类型有关,二级以及二级以上的指针的大小是四个字节(32位机)
2,*p操作内存
在指针声明时,*号表示所声明的变量为指针
在指针使用时,*号表示 操作 指针所指向的内存空间中的值
*p 相当于通过地址(p 变量的值)找到一块内存;然后操作内存
*p 放在等号的左边赋值(给内存赋值)如*p = 10;
*p 放在等号的右边取值(从内存获取值)inta = *p;
3,指针变量和它指向的内存块是两个不同的概念
//含义 1 给 p 赋值 p=0x1111;
只会改变指针变量值(改变其指向), 不会改变所指的内容; p = p +1;
p++加的是其步长而不是真正的1
//含义 2 给*p 赋值*p='a';
不会改变指针变量的值,只会改变所指的内存块的值
//含义 3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
//含义 4 =左边 char *p
//含义 5 保证所指的内存块能修改
4,指针是数据类型,是指它指向内存空间的数据类型
含义 1:指针步长(p++) ,根据所致内存空间的数据类型来确定
p++=->(unsigned char )p+sizeof(a);
结论:指针的步长,根据所指内存空间类型来定。
注意: 建立指针指向谁,就把把谁的地址赋值给指针.
不断的给指针变量赋值,就是不断的改变指针变量(和所指向内存空间没有任何关
1.2:间接赋值(*p)是指针存在的最大意义
1)两码事:指针变量和它指向的内存块变量
2)条件反射:指针指向某个变量,就是把某个变量地址否给指针
3)*p 间接赋值成立条件:3 个条件
a)2 个变量(通常一个实参,一个形参)
b) 建立关系,实参取地址赋给形参指针
c) *p 形参去间接修改实参的值
案例
Int iNum = 0;
//实参
int *p = NULL;
p = &iNum;
iNum = 1;
*p =2 ;
//通过*形参 == 间接地改变实参的值
*p 成立的三个条件:
4)引申: 函数调用时,用 n 指针(形参)改变 n-1 指针(实参)的值。
//改变 0 级指针(int iNum = 1)的值有 2 种方式
//改变 1 级指针(eg char *p = 0x1111 )的值,有 2 种方式
//改变 2 级指针的(eg char **pp1 = 0x1111 )的值,有 2 种方式
//函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p,来改变实参,把运算结果传出来。
//指针作为函数参数的精髓。
1.3:理解指针必须和内存四区概念相结合
1)主调函数 被调函数
a) 主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
b) 被调用函数只能返回堆区、全局数据,不能返回栈上数据
2)内存分配方式
a) 指针做函数参数,是有输入和输出特性的。
1.4:应用指针必须和函数调用相结合(指针做函数参数)
文章图片
指针做函数参数,问题的实质不是指针,而是看内存块,内存块是 1 维、2 维。
1)如果基础类 int 变量,不需要用指针;
2)若内存块是 1 维、2 维,需要指针。
1.5:一级指针典型用法(指针做函数参数)
一级指针做输入int showbuf(char *p)int showArray(int *array, int iNum)
一级指针做输出int geLen(char *pFileName, int *pfileLen);
理解
主调函数还是被调用函数分配内存
被调用函数是在 heap/stack 上分配内存
1..6:二级指针典型用法(指针做函数参数)
二级指针做输入
int main(int arc ,char *arg[]);
字符串数组
int shouMatrix(int [3][4], int iLine);
二级指针做输出
int Demo64_GetTeacher(Teacher **ppTeacher);
int Demo65_GetTeacher_Free(Teacher **ppTeacher);
int getData(char **data, int *dataLen);
Int getData_Free(void *data);
Int getData_Free2(void **data);
//避免野指针
理解
主调函数还是被调用函数分配内存
被调用函数是在 heap/stack 上分配内存
1.7: 三级指针输出典型用法
【c语言学习历程|c语言指针进阶总结】三级指针做输出
int getFileAllLine(char ***content, int *pLine);
int getFileAllLine_Free(char ***content, int *pLine);
理解
主调函数还是被调用函数分配内存
被调用函数是在 heap/stack 上分配内存
1.8: 杂项,指针用法几点扩充
1)野指针 2 种 free 形式
int getData(char **data,
int *dataLen);
int getData_Free(void *data);
int getData_Free2(void **data);
2)2 次调用
主调函数第一次调用被调用函数求长度;根据长度,分配内存,调用被调用函数。
3)返回值 char */int/char **4)C 程序书写结构商业软件,每一个出错的地方都要有日志,日志级别
1. 9:一般应用禁用 malloc/new因为使用malloc/new就会伴随着内存泄漏
二级指针与多级指针
使用指针申请二维空间
#include #if 0
//利用返回值进行申请不连续的二维空间
void ** Shenqin(int base,int row,int line)
{
void **p = (void **)malloc(sizeof(void*)*row);
for(int i = 0;
i|
文章图片
2, 指针和数组的巨大区别
文章图片
3,字符与一级指针的内存模型
文章图片
4, const基础
int main(){
const int a;
//
int const b;
const char *c;
char * const d;
char buf[100]
const char * const e ;
return 0;
}
int func1(const )
初级理解:const 是定义常量==》const 意味着只读
含义:
//第一个第二个意思一样 代表一个常整形数
//第三个 c 是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改)
//第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)
//第五个 e 一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)
Const 好处
//合理的利用 const,
//1 指针做函数参数,可以有效的提高代码可读性,减少 bug;
//2 清楚的分清参数的输入和输出特性
结论:
//指针变量和它所指向的内存空间变量,是两个不同的概念。 。 。 。 。 。
//看 const 是放在*的左边还是右边 看 const 是修饰指针变量,还是修饰所指向的内存空变
二位数组图解
文章图片
推荐阅读
- c语言学习历程|c语言指针进阶(一)
- c语言学习记录|C语言指针进阶学习
- C语言进阶|【C语言进阶16——通讯录(基础版、动态内存版、文件管理版)】
- C语言进阶|【C语言进阶14——文件操作(1)】
- c语言进阶——多维数组本质及指针数组的应用分析
- C语言进阶|【C语言进阶7——数组和指针的练习(1) - 学习sizeof 和 strlen,看完这一篇就够了】
- C语言进阶|【C语言进阶6——指针的进阶(3)-总结数组和指针】
- 带头和尾指针的双链表中的排序插入
- 修改二叉树以仅使用右指针获得先序遍历