指针:
指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑储存器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
总结:指针是个变量,存放内存单元的地址,地址唯一标识一块内存空间。
指针的大小是固定的,4/8个字节(32位平台/64位平台)
如何编址?答:对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址时产生一个电信号(0或者1),那么32根地址线产生的会是,从全0到全1,这里就有2的32次方个地址。每个地址标识一个字节,那我们就可以给2^ 32 byte== 2^ 32/1024kb == ^ 32/1024/1024mb == 2^32/1024/1024/1024gb==4GB的空间进行编址。
指针是有类型的,指针的类型决定了指针的±整数的步长(指针向前或者向后走一步有多大(距离)),指针解引用操作的时候的权限(能操作几个字节)
指针运算:
1.指针±整数:指针加减整数就是往前或者往后走整数个的类型大小,比如int*p,p+2 就是p往后走俩个单位,也就是8个字节。
多级指针+1就是加4个字节(二级,三级,四级……)
2.指针-指针:得到的是指针之间元素的个数。 (俩个指针必须指向同一块空间)
注:小地址-大地址=元素的个数(负数)
3.指针的关系运算:指针比较大小
注:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
二级指针
指针也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针。
指针和数组
指针和数组名:数组名表示的是数组首元素的地址。
指针通过*(p+i)来访问数组元素
指针数组
指针数组是数组,是存放指针的数组。
int* p[10]
注:[]的优先级比* 高,所以p先和[]结合,说明是数组,是一个存放10个指针的数组。
在认知上,我们认为所有的数组都是一维的。
数组传参会有退化(降维)问题。降低内存开销,但是并不代表没有开销,开销是指针的内存大小(4个字节)。如果不退化,就会发生硬拷贝,造成效率的降低。
**重要 ** 数组传参时,会降维成指向其内部元素类型的指针。
一维数组传参,用int a[] ,int a[10],int *a来接收(三个都可以)。
指针数组传参,用二级指针,int *a[10]接收。(俩个都可以)。
二维数组传参,不能用二级指针接收,用数组指针来接收。int a[10]【10】,int a【】[10]来接收。
三维数组传参,int a【10】【10】【10】,int a【】【10】【10】来接收。
函数形参的设计只能省略第一个[]的数字
数组指针
数组指针是指针,指向数组的指针。
int(*p)[10]
注:p先和*结合,说明p是一个指针变量,指向的是一个大小为10个整形的数组。
既然数组指针指向的是数组,那么数组指针中存放的是数组的地址。
解引用
对指针解引用就是它指向的对象。
使用a的存储空间叫做a的左值
使用 a的内容叫做a的右值
void * 可以接受任意类型
char的指针解引用就只能访问一个字节,而int的指针解引用就能访问四个字节。
函数指针
函数名和取地址函数名都代表的是函数的入口地址。
void (*pfun1)() ; 函数指针
函数指针数组
int (*parr1[10])();
指向函数指针数组的指针
void(*(星ppfunArr)[10])(const char星) = &pfunArr;
回调函数
回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的内容时,我们就说这是回调函数。