普通指针(一级):
定义:
指针=地址
取地址符:&变量名(获取该变量的地址) //针对所有变量都适用
printf(“%d”,&a); 输出地址 //%d ->10进制 ,%p->16进制
//scanf里用&也是一样的道理,通过地址才能在scanf函数中形参中把值带过来
使用:
*指针变量:解引用,间接访问符
例如:int* p=&a;
*P=100;//a=100;
指针变量和普通变量
相同点:
- 都能改变
- 都有地址
不同点:
- 指针变量可以解引用,普通变量不可以
总结:
int p;//定义整型变量
int* p; //定义整形地址变量
&a; //整形地址变量
p=&a;//整形地址变量p保存整形a地址值
int*p=&a;//把上面两步合并
指针字节大小:(与类型无关)
由平台决定
X86:32位操作系统;2^32 一个字节8位,这种情况下,指针4个字节
x64:64位操作系统 2^68 这种情况下,指针8个字节
一字节=-128到127 256 2^8
1TB=1024GB;
1GB=1024MB;
1MB=1024KB;
1KB=1024B;
1B=8b;
补充:
(1)Int*p1,p2,p2;
//p1:指针变量,p2,p3:整型变量
(2)typedef int* INT;
INT p1,p2,p3; //此时,三个均为指针变量,等价于Int*p1,*p2,*p2;
(3)#define INT int*
INT p1,p2,p3; //此时,仅第一个为指针变量,等价于Int*p1,p2,p2;
习题练习
eg1:
//知识点:指针类型必须严格相等才能赋值(就是变量什么类型,指针什么类型)
char a;
short b;
int c;
unsigned long d;
double e;
float f;
//定义指针p1,保存a的地址
char* p1 = &a;
//定义指针p2,保存b的地址
short* p2 = &b;
//定义指针p3,保存c的地址
int* p2 = &c;
//定义指针p4,保存d的地址
unsigned long* p2 = &d;
//定义指针p5,保存e的地址
double* p5 = &e;
//定义指针p6,保存f的地址
float* p6 = &f;
eg2:
int a, b, c;
int* p1 = &a;
int* p2 = &b;
int* p3 = &c;
//通过p1,将a的值改为20,并输出;
*p1 = 20;
printf("%d", *p1);
//通过p2,将b的值改为30,并输出;
*p2 = 30;
printf("%d", *p2);
//通过p1,p2,p3,将c的值改为a×b,并输出;
*p3 = *p2 * *p2;
printf("%d", *p3);
//定义指针p,指向a
int* p = &a;
//通过p1,将a的值改为10;
*p1=10;
//将p指向b,并通过p将b的值改为20
int*p = &b;
*p = 20;
//将p指向c,并通过p将c的值改为30
p = &c;
*p = 30;
//通过p输出a,b,c的值(需要多条语句)
p = &a; printf("%d", *p);//输出a的地址;
p = &b; printf("%d", *p);//输出b的地址;
指针的好处:
(1)通过形参带回值问题
例:
//交换两个数的值
//形参与实参的地址不一样,无法直接改变,需要地址改变
//形参是局部变量
//只有指针才能通过调用函数改变其值;
void MyScanf(int* a, int* b)
{
*a = 1;
*b = 0;
}
int main()
{
int a ;
int b ;
MyScanf(& a, & b);
return 0;
}
eg3:
//交换变量
void Swap(int *a,int* b)
{
int *temp=a;
a = b;
b = temp;
}
void Swap(int *a,int* b)
{
int temp=*a;
*a = *b;
*b = temp;
}
//如下错误:对野指针进行解引用
void Swap(int *a,int* b)
{
int *temp=*a;
*a = *b;
*b = *temp;
}
(2)解决函数多个返回值问题(return 两部分)
int Operate(int a,int b,int* sum,int* mul)
{
*sum=a+b;//主函数里把地址传过来,该函数内部对其解引用替换值
*mul=a*b;
}
int main()
{
int sum,mul;
Operate(1,2,&sum,& mul);
}
二级指针
二级指针pp理解:
*pp//pp指向的值
**pp //pp指向的值的指向,就是p的指向
输出参数:外部传指针,内部解引用
void Myscanf(int*p1)
{
*p1=100;
}
int *p=&a;//p保存a的地址,*p对a解引用
int * *pp=&p; //pp是int的二级指针
//&&a错误
*&a=a; //对的,对a取地址又对其解引用
//&*a错误,不能对a解引用
例题分析
eg1:
int a = 10;
int b = 20;
int* p = &a;
*p = 100; //a=100;
p = &b;
*p = 200; //b=200;
int** pp = &p;
**pp = 1000;//解两次引用,b=1000;
*pp = &a;
**pp = 2000; //a=2000;
结果:a=2000,b=1000;
int ***ppp =&pp;
=int* **pp,三级指针保存二级指针地址
***ppp=1;//a=1;
结果a=1;
补充://对野指针的理解
int *p=&a
printf(“%d”,*p); //可以
但是
p=NULL;
printf(“%d”,*p);//不行,不能对空进行解引用
但是,如下情况:
定义Fun(p)函数,在内部对p置空,调用Fun(p),再输出printf(“%d”,*p)
void Fun(int* p)
{
p = NULL;
}
int main()
{
int a = 10;
int* p = &a;
Fun(p);
printf("dn", *p);
return 0;
}
//此时发现Fun函数并没有起作用,因为:A函数调用B函数,如果需要通过修改A中实参的值,则必须传指针,在B中再解引用
//fun函数未被执行,想要通过另一个修改其值,必须传指针,函数内部解引用(加*)
//如下所示,会导致错误
void Fun(int** p)
{
**p = NULL;
}
总结:
NULL空指针,当前为无效指针,相当于告诉用户该指针作废
野指针:没有访问权限,指针定义时未初始化,易产生野指针
如有错误,还请评论告诉我,谢谢❤



