指针
指针是什么(初级)
指针是内存中一个最小单元的编号,也就是地址。
指针变量,是用来存放内存地址的变量。
指针变量
我们可以通过&(取地址操作符)取出变量的内存其实就是地址,把地址存放在一个变量中这个变量就是指针变量。
综合上面可知指针用来存放地址,那么指针的大小和地址有关,那么计算机中地址有多大呢?
计算机一般都是32/64位,对于32位机器那么最大划分的地址也是32位,既是4个字节
同理对于64位计算机也就是8个字节。
指针类型
char*存放char类型变量的地址
short*存放short类型变量的地址
int*存放int类型变量的地址
指针类型的类型决定了指针向前向后走一步的距离。
如:char*,每次指针向后/向前走一个字节,int*走4个字节
野指针
野指针就是指向的位置是不可知的(随机的、不正确的、没有明确限制的)
野指针的成因
1.指针未初始化
2.指针越界访问
3.指针指向的空间释放
如何规避野指针
指针初始化
int*p=NULL;
小心指针越界
避免返回局部变量的地址
指针使用前检查有效性
指针运算
指针+-整数
指针-指针
指针的关系运算
指针和数组
从运行结果可以知道数组名表示的是数组首元素的地址。int*p=arr//p存放的是数组首元素地址。
p+i其实计算的是数组arr下标为i的地址。
那么我们可以通过指针来访问数组
*(p+i);
二级指针
指针变量也是变量,是变量就有地址,指针变量地址存放的变量就是二级指针。
**p二级指针
指针数组
存放指针的数组
int* arr[5];
指针进阶
指针的解引用
指针的类型决定了,对指针解引用的时候有多大权限(能操作几个字节)
指针就是个变量用来存放地址,地址唯一标识一块内存空间
指针的大小是固定字节4/8(32位平台,64为平台)
指针有类型,指针的类型决定了指针的步长,指针解引用操作时的权限
指针运算
字符指针 char *
p指向字符串,打印p与打印字符串arr相同。arr存放字符串首元素地址指针p也
把字符串首字符的地址存放到指针变量p中,通过指针变量就可以访问整个字符串的字符。常量字符串不能被更改
&数组名VS数组名
对于下面数组
arr和&arr分别是什么
arr是数组名,数组名表示数组首元素的地址。
那&arr是什么
来看这段数组代码
#include
int mian()//主函数入口
{int arr[10]={0};printf("%p\n",arr);//打印地址printf("%p\n",&arr);//运行可以看到两个的打印结果一致//虽然结果一致,但是表示的含义并不一样return 0;
}
为了更详细的区分 arr和&arr我们来看下面一段代码
#include
int main()
{int arr[10]={0};printf("arr=%p\n",arr);printf("&arr=%p\n",&arr);printf("arr+1=%p\n",arr+1);printf("&arr+1=%p\n",&arr+1);return 0;
}
运算结果下
根据上面代码我们发现,其实&arr和arr一样,虽然值是一样的,但&arr表示的是数组的地址,而不是首元素的地址。本例&arr的类型是int(*)[10];是一种数组指针类型。
数组的地址+1,跳过整个数组的大小,所以&arr+1相对于&arr的差值是40。
数组指针
数组指针是用来指向数组的指针。
//注意区分指针数组和数组指针的区别
int *p1[10];//指针数组,这是个数组
//[]的优先级高于*
int (*p2)[10];//数组指针,这是个指针,存放数组的地址
//为了使其成为数组,要用()来增加*的优先级
既然数组指针是指向数组的指针,那么存放的应该是数组的地址
来看下面一段代码
int main()
{int* p=NULL;//整型指针-用来存放整型的地址char* p=NULL;//字符指针,用来存放字符地址int arr[5]={1,2,3,4,5};//arr--数组首元素地址//&arr[0]--数组首元素地址//&arr--整个数组的地址int (*p)[10]=&arr[5];//把数组arr的存储地址赋值给数组指针变量p//这样就可以通过p来操作数组arr了但是一般我们不这样使用return 0;
}
为了便于大家理解举下面一个例子
int main()
{char*arr[5];//定义一个指针数组// 那么该怎样保存这个指针数组的地址呢//首先我们知道这是个数组肯定需要用数组指针来保存//其次数组的类型是char*//所以有下列表示char*(*pa)[5]=&arr;//char* pa指向数组的元素类型//[5] pa所指向的数组5个元素//* 说明pa是指针//数组类型(*pa)[数组元素个数] 数组指针 char arr2[10]={0};char(*p)[10]=&arr2; return 0;
}
数组指针的使用
来看下面一段代码:打印数组的内容
#include
int main()
{int arr[10]={1,2,3,4,5,6,7,8,9,0};int(*p)[10]=&arr;for(int i=0;i<10;i++){//*p这里可作看成arrprintf("%d ",(*p)[i]);//打印数组内容}return 0;
}//一般不使用这种方法
再来看下面这段代码和上面代码功能相同,也是我们一般写法。
#include
int main()
{int arr[10]={1,2,3,4,5,6,7,8,9,0};int *p=arr;int i=0;for(i=0;i<10;i++){printf("%d ",*(p+i));}return 0;
}
//对比以上两种方法显然第2种比较方便
//对于数组指针一般用于至少二维数组以上才比较方便
一般需要用数组指针的情况如下示例代码(这里比较复杂可多看几遍有助于理解)
#include
void prit1(int arr[][],int x,int y)
{int i=0;for(i=0;i{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}}prit1(arr,3,5);//打印二维数组//arr数组名就是首元素地址,把arr每一行看作一个元素那么arr就有三个元素,每个元素有5个整型的大小//此时首元素地址就是第一行//既然arr是首地址,首地址又是第一行的元素(既是一个一维数组其中有5个元素),那么就可以用数组指针来打印输出prit2(arr,3,5);//打印二维数组//容易得知两个打印结果相同return 0;
}
指针数组
来看下面请这段代码
int main()
{int arr[10]={0};//整型数组char ch[5]={0};//字符数组int *arr[5];//存放整型指针的数组char *err[10];//存放字符型指针的数组 return 0;
}
指针数组的用法
先看下面这段代码,一般这种代码很少用
int main()
{int a=10;int b=20;int c=30,d=40;int *arr[4]={&a,&b,&c,&d};//用来存放a,b,c,d的地址for(int i=0;i<4;i++){printf("%d ",*(arr[i]));//解引用操作}return 0;
}
再来看下面这段代码
int main()
{int arr1[]={1,2,3,4,5};int arr2[]={3,4,5,6,7};int arr3[]={4,5,6,7,8};int* arr4[]={arr1,arr2,arr3};//这里数组名相当于数组首元素地址int i=0;for(i=0;i<5;i++){int j=0;for(j=0;j<5;j++){printf("%d ",*arr4[i]+j);//打印数组中的所有元素}printf("\n");//每打印一个数组,换行}return 0;
}
上一篇:C语言/动态内存管理函数
下一篇:每日学术速递3.15