C语言--指针详解

2024-01-08 17:33:17

一,指针的基本概念及运用原理

1,指针基本信息

指针实际上就是变量的地址,例如:int a=4,p=&a,p存放的就是a变量的地址,printf("%p",p);打印的是第一个字节的地址(一个内存单元为一个字节,int类型占有个字节,占四个内存单元,打印p,打印的是小地址的内存单元)

指针的大小取决于地址所占据的内存空间,而地址所占据的内存空间取决于是32位还是64位的机器,若为32位的,则指针占4个字节,若为64位,则指针占8个字节。

2,指针类型

1,指针类型决定了它决定了解引用时的权限(一次能操作几个字节)

例如:int a=0x11223344;char* p=&a;*p=0;

因为char*类型的指针只能访问一个字节,又因为a为整型变量,有4个字节,所以只改变四个字节中的一个字节的内容。

2,指针类型决定指针向前走或向后走的一步有多大。

因为p是char*类型的指针,所以p+1,只能往前走一个字节的内存单元,即改变的是a中第二个字节的数值。

3,利用指针打印数组

二,指针的运算

1,指针加减整型

在数组中,int* p = arr;首先得到的是数组arr首元素的地址,p指针加1,可向后访问数组中的下一个元素(即第二个元素)。若p+2,则访问的是第三个元素。

2,指针减指针

指针减指针算出的是指针与指针间的元素个数(注意:两个指针所指的位为同一块空间,即同一个数组的不同元素的地址)

指针减指针可算出字符串的长度

3,指针的关系运算(地址间比较大小)

三,两个特殊类型的指针

1,void*泛型指针

可用来接收任意类型的地址,但不能直接进行指针的加减运算和解引用运算。

2,野指针

成因:1,野指针未初始化。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2,指针越界访问。 例如:int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;? ? ? ? ? ? ? ? ? ? ? ?printf(“%d”,*(p+10))报错!因为p+10越界访问了? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3,指针所指的空间被释放。例如:调用函数中会临时开辟空间给变量,当调用完毕时,临时创建的空间会被释放,若在函数中运用指针,函数调用后,该指针就不能使用了

3,空指针NULL

NULL是C语言中的标识符常量,值为0,0也为地址,这个地址是无法使用的,对该地址进行读写都会报错。

四,用指针访问数组

printf("%d", *(p + i));==printf("%d", *(arr + i));==printf("%d", arr[i]);==printf("%d", p[i]);

一维数组传参时,传的是首元素地址,所以不能在函数中,计算数组个数int sz=sizeof(arr)/sizeof(arr[0]);因为在函数中sizeof(arr)arr首元素的地址,所以在32为机器下,sz=1;故应该在主函数中计算sz,并传参到函数中。

五,不同的指针类型

1,二级指针

int a=1;int*p=&a;int**pp=&p;这时pp为二级指针。将a的地址储存在p中,再将p的地址放到pp中。int* *pp=&p;第二个*代表pp为一个指针,int*为p的类型。

2,字符指针

p为指针,指针指向字符,故为字符指针。char*p=“abcde”;把字符的首元素地址放到p中,即p指向的是a的地址。我们可以将字符串想象成数组.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 所以printf(“%c\n”,"abcde"[3]);==printf(“%c\n”,p[3]);

例题

补充:const的用法

int a=1;const int*p=&a;==int const *p=&a;这时const修饰*p,故a的值不能进行改变,即不能通过修改p指向的空间的内容,但p的值是不受限制的,故p=&b,是正确的。

int a=1;int*const p=&a;这时const修饰的是p变量,故p不能进行修改,故p=&b,是错误的。但*p不受const的限制,即可以通过修改p指向的空间的内容,即*p=2,语法是正确的。

在上述例题中,str1和str2分别表示str1数组和str2数组的首元素地址,所以str1!=str2,

而内容相同的字符串常量只能保存在一块内存中,所以str3和str4,这两个地址都指向字符串的首元素地址。所以str3==str4

3,数组指针(指向数组的指针)

int*p1[10]:p1是数组,数组里面有10个元素,每个元素的类型是整型指针

int (*p2)[10]:p2是指针,该指针指向数组,数组中有10个元素,每个元素是整型的

利用数组指针打印二维数组:

4,函数指针(用来存放函数的地址)

ine(*fp)(int,int)=&add;pf中存放的add函数的地址,add函数的两个参数是整形,返回类型为也为整型。

例题:void(*signal(int,void(*)(int)))(int)

signal是一个函数,它的参数有两个一个为整型,一个为函数指针,这个函数的参数为int型,返回类型为void。signal这个函数的返回类型为函数指针,这个函数的参数为int型,返回类型为void。

用typedef可将复杂的类型从命名,例如上述复杂的式子可简化为下面两个分式,

typedef? ? unit void(*)(int);

unit signal(int,unit)

5,函数指针数组(把函数指针放到数组中)

文章来源:https://blog.csdn.net/2302_81705247/article/details/135396639
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。