C++指针 2021.4.20

  • 指针变量里面存储了一个地址,可以是常量、全局变量、局部变量、堆变量(new)的地址,还可以是函数(代码)的地址
空指针

空指针又称万能指针,可以指向任何带类型的指针(地址)
p=&x; x可以是基本数据类型,也可是对象/结构体类型。
p=&table;
p=&book;

int a = 3;
void *p1;
p1 = &a;//p1指向a的纯地址,但并不理解成int
int *pi = (int*)p1;
//强制类型转换,将p1理解成pi,语法逻辑都正确
float *pf = (float*)p1;
//强制类型转换,将p1理解成pf,语法正确,逻辑错误

eg.C语言库函数qsort,快速排序,可以对任意类型的数组数据进行排序

void qsort(void *base, int nelem, unigned int width, int(*pfCompare)(const void*, const void*))
   //数组起始地址,数组元素的个数,每个元素的大小(字节为单位)

int函数名(const void *d1, const void *d2);比较元素大小的指针函数,实参是程序员自定义的函数
虽然这个也没写具体原理,,,但是从此我知道了会用就行

int cmp1(const void *a, const void *b){
	return *(unsigned int *)a - *(unsigned int *)b;//从小到大排序
}
int cmp2(const void *a, const void *b){
	return *(unsigned int *)b - *(unsigned int *)a;
}
int cmp3(const void *a, const void *b){
	const unsigned int *p1, *p2;
	p1 = (const unsigned int*)a;//把void*转化成int* 
	p2 = (const unsigned int*)b;//把void*转化成int* 
	return (*p1%10)-(*p2%10);
}
返回指针值的函数

被调函数的返回结果是一个地址,函数的类型是指针类型

int *max(int *x, int *y){
	int *pt;
	if(*x > *y)
		px = x;
	else
		pt = y;
	return pt;
}

不要试图返回局部变量的地址。。。它被释放了
下面为错误示例:

int *max(int *x, int *y){
	int *pt;
	if(*x > *y)
		px = x;
	else
		pt = y;
	return &pt;
}
局部变量地址
int *max(int *x, int *y){
	int *pt;
	if(*x > *y)
		px = x;
	else
		pt = &y;
	return pt;
}
局部变量(形参)的地址

在这里插入图片描述

指针数组

每一个元素可以存放地址
int *p[4];

  • []*优先级高,所以等价于int *(p[4])
  • p[]是数组,p[4]存放四个元素
  • 每个元素p[i]是一个int*,即整数数据的地址,或者一个int数组的首地址
    在这里插入图片描述
    直观上,每个指针都可以指向一段内存空间,可以理解为二维数组,说是任意维度更恰当。
void main(){
	int a[12] = {1,2,3,...,11,12};
	int *p[4]//指向四段内存
	for(int i = 0; i < 4; i++)
		p[i] = &a[i * 3];
	cout << p[3][2] << endl;
}

p[3][2] = *(p[3] + 2) = *(*(p + 3) + 2);

  • 指针数组与二维数组的比较
    在这里插入图片描述
    //要注意最后一个不是*(p+3+2)而是*(*(p + 3) + 2)
  • 常见应用场景:实现字符串数组,数组中的每个字符串长度不一
  • char *str[] = {"China", "Japan", "America"};
指向指针的指针
int i, *p;
p = &i;
int **pp;
pp = &p;

pp=&&i;//不能连续取地址,第一次取出来的那个地址其实是个值,无法据此取到第二个地址
pp = & i; //一看就不对,pp为只想指针的指针变量,其基类型是指向整型数据的指针变量,而非整形数据

  • 经典用途:字符串数组(好像不能直接赋值全部,只能分开单独赋值。 能 )
    在这里插入图片描述
其他说明:
  1. 指针变量可以有空值,不指向任何地址。(虽然有#define NULL 0)(p=NULL相当于p=0但不建议写p=0)
  2. 两指针可以相减,不可以相加。若要进行相减运算,则两指针必须指向同一数组,结果为相距的数组元素个数
  3. 指向同一数组的两个指针可以比较大小:p2>p1指p2在p1的后面
动态分配内存

静态开辟的内存(栈)会存在不足或者浪费。一i那次在程序中要根据实际需要动态开辟空间——
利用new运算符开辟空间,空间的地址必须用个指针保存下来,才不会丢失
ps1. 当内存中没有足够的内存给予分配时,new运算符返回空值NULL;
ps2. new出来的空间,不能在分配空间时进行初始化,且除非重新开机,要手动用delete收回(二者配套,delete无其他使用)

int *p;
p = new int;
p = new int(6);//赋初值6
p = new int[6];//申请一个数组,首地址送给p
//开辟一个数组,每个元素都是一个int*
int **pp;
pp = new int*[100];//int*[rows]
for(int i = 0; i < 100; i++)
	pp[i] = new int[5];

关于delete:
在这里插入图片描述
这一个示例是为了表示不要重复删除一块内存空间

int *q = new int(5);
p = q;
delete p;
cout << *q << endl;

这一个示例是为了避免野指针出现,保证删除后这个成为空指针

int *p = new int;
*p = 5;
if(p){
	delete p;
	p = NULL;
}
指针数组和指向指针的指针
  • int a[3][4];连续存放3行4列整数,自动分配空间
  • int(*p)[4];连续存放未知(n)行4列整数的第一行,可以p=a; ,p = &a[i]p是a上按行游走的指针
    int(*p)[4]相当于指向有四个元素的一维数组,比如说a[1]
  • int **a 等价于 int *a[]

int *p[3];3行整数,可以不连续,每行整数个数未知
int **p;n行整数,可以不连续,每行整数个数未知

p = new int*[3];
p[0] = new int [4];
p[1] = new int [4];
以上都是合法的
下面非法:(因为连续性不同)
p = a;
a = p;
const指针

记得const要在定义同时必须赋值

  • const 修饰指针:1-常指针
    int r = 6;
    int * const pr = &r;
    数据类型 * const 指针变量名
    这样仅仅表明指向这个地址不变,不能再访问其他的内存单元了,但是仍然可以更改这个内存单元的值
    用途:1. 数组名为常指针(禁写指针),int a[10],不能a++; 2.考试

  • const型指针2-指向常量的指针变量(不允许通过指针间接更改单元内容,但是可以直接更改
    const 数据类型 * 指针变量名
    用途:日常常用

  • const型指针3-指向常量的常指针变量
    const 数据类型 * const 指针变量名
    定义后没不允许通过指针变量改变所指向的对象的值,也不允许改变指针变量的值,特少见

const char *str3; str3 = “qwq”;是正确的,因为“qwq”是一个常量,是不能修改的,必须要有const,这玩意儿不是拷贝的,是把变量地址送给指针。
char str[80] = {“qaq”};这才是拷贝的
char str[80]; str = “qwq”;是错的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值