指针
一指针的概念
1.为了方便访问内存中的内容,给每一个内存单元编导,我们称这个编号为地址,也就是指针
2.指针也是一种数据类型,所以指针有自己的内存,存储的是地址(编号)
四要素
int* p=10;===>int*就是指针本身的类型,p就是指针名,int就是指针指向的类型
1.指针本身的类型 除去指针名,剩下的就是指针本身的类型
2.指针指向的类型 除去指针名和一个*,剩下的就是指针指向的类型
3.指针本身的内存 用来存储指向内容的**地址**(
指针里面,只存编号)(四个字节)
4.指针指向的内存 可以是各种类型
二指针的定义
1.运算符
定义时,表示定义的是一个指针,其他时候表示解析引用(取内容)
&:取首地址符
定义
定义一个指针,指针也是一种数据类型
指针类型==》指针名
1.除去指针名,剩下的就是指针类型
2.除去指针名和一个*,剩下的就是指针指向的类型
int* p;
//定义了一个int*类型的指针,叫做p
//p这个指针,本身的类型是int*
//p这个指针,指向的类型是int
三指针的内存
指针也是一种数据类型,所以指针有自己的内存,存储的是地址(编号)
编号是一个数字==》十六进制数
1.所有的指针,不论类型,在内存中都只占4个字节的内存
int* a;
short* b;
char* c;
float* d;
double* e;
printf("%d
",sizeof(a));
printf("%d
",sizeof(b));
printf("%d
",sizeof(c));
printf("%d
",sizeof(d));
printf("%d
",sizeof(e));
四 指针的初始化和赋值
1.用对应类型变量的地址赋值
int num=10;
int* p=#//初始化
//必须是对应的类型
short sh=20;
short* p1;
p1=&sh; //赋值
2.用相同类型的指针直接给值
int num=10;
int* p=#
int* p1;
p1=p;
int* p1=p;
3.直接用地址给值
int* p=(int*)0x36;
//(int*)==>强制转换类型
4.用数组名给值
//数组名就是数组的首地址!!!
int arr[5]={1,2,3,5,6};
int* p=arr;
*p取的是数组里的第一个内容,1
5.用字符串给值
char arr[10]="abcd";
char* p=arr;
char* p="abcd";
printf("%x",p);//打印的是一个十六进制的数,是p的地址
printf("%s",p);//打印的是abcd
cout<<p<<endl<<;//打印的是abcd
//char*类型的指针,可以直接输出整个字符串,直到遇见' '停止
6.置空
1,有时候,指针定义了,还没有指向,
2,或者是,指针用完了,没有指向了
此时不知道指向哪里
此时的指针很危险==》(野指针)
所以,这些情况下的指针,我们给他们一个固定的指向
指向0地址
int* p1=NULL;
int* p2=nullptr;
int* p3=(int*)0x0;
char* p4=(char*)0x0;
7.多级指针
int a=10;
int* p=&a;
*p指的是:取p指向的内存里面所存的东西
而p指向的是a,a里面存的是10
所以打印的*p的值为10
int a = 10;
cout << "a=" << a << endl;//10
cout << "&a=" << &a << endl << endl;
int* a1 = &a;
cout << "a1=" << a1 << endl;
cout << "&a1=" << &a1 << endl;
cout << "*a1=" << *a1 << endl << endl;
int** a2 = &a1;
cout << "a2=" <<a2<< endl;
cout << "&a2=" << &a2 << endl;
cout << "*a2=" << *a2 << endl << endl;
int*** a3 = &a2;
cout << "a3=" << a3 << endl;
cout << "&a3=" << &a3 << endl;
cout << "*a3=" << *a3 << endl <<;
cout<<"***a3="<<***a3<<endl;
/*打印的结果
a=10
&a=00F7FA44
a1=00F7FA44
&a1=00F7FA38
*a1=10
a2=00F7FA38
&a2=00F7FA2C
*a2=00F7FA44
a3=00F7FA2C
&a3=00F7FA20
*a2=00F7FA38
***a3=10
*/
例题
short sh = 10;
short* psh1 = &sh;
short* psh2 = psh1;
short** ppsh1 = &psh2;
short** ppsh2 = ppsh1;
short*** pppsh = &ppsh2;
***pppsh = 9;
cout << "sh=" << sh << endl;
//最后输出的sh=9,***pppsh是直接取指sh里的内容,可以直接修改
![image-20201130192557126](C:Users86186AppDataRoamingTypora ypora-user-imagesimage-20201130192557126.png
五.指针的加减法
核心:指针本身的值(指向)有没有变化
指针的偏移
不改变指针的指向
1.指针可以加上或者减去一个整数
2.指针加上或减去一个整数后,实际上是进行了偏移
偏移的范围是加上或者减去的整数个单位
单位:指针指向的类型在内存中所占的字节数
偏移:指针指向不变,但是根据偏移量取内容
int num = 10;
int* p = #
cout << p << endl; //004FF728
cout << "*p="<< *p << endl; //*p = 10
cout << p + 1 << endl << endl; //004FF72C 加l4
short sh = 20;
short* psh = &sh;
cout << psh << endl; //004FF710
cout << psh + 1 << endl; //004FF712 加了2
六.指针的自增自减
自增自减,会改变指向
++:表示指针向后移动一个单位
--:表示指针向前移动一个单位
单位:指针指向的类型在内存中所占的字节数
七.指针与一维数组
通过指针遍历一维数组
int arr[5] = { 1,2,3,6,5 };
int* p = arr;
cout << *p << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
int* parr = arr;
for (int i = 0; i < 5; i++)
{
cout << parr[i] << endl;
}
printf("
");
//输出的效果都是一样的
//parr和arr是一样的
//但是arr是一个常量
cout << *(parr+0) << endl;
cout << *(parr + 1) << endl;
/*
*(parr+0) <==> parr[0]
*(parr+1) <==> parr[1]
*(parr+2) <==> parr[2]
结论:
*(p+n)等价于p[n]
*/
通过指针遍历二维数组
int arr[3][4] = {
{1,5,3},
{6,3,2},
{5,6,9}
};
/*int* p = &(arr[0][0]);
*(p+n) <==> p[n]
arr[0][0] ==> *(arr[0]+0) ==> *(*(arr+0)+0) ==> *(*(arr))
&(*(*(arr)))==>(*(arr))==>*(arr)==>arr[0]
*/
int* p = arr[0];
for (int i = 0; i < 12; i++)
{
cout << p[i] << endl;
}
//可以将这个二维数组打印出来
存储模式
1.小端模式(vs)
存储:低字节存数据的低位
读取:从高位向低位读取(逻辑习惯)
2.大端模式
存储:低字节存数据的高位
读取:从低向高读取(阅读习惯)