关于指针的一些注意点(持续记录)

一级指针,二级指针

一级指针

int a;
int *p ;
p=&a ;//也可以写作 *p = a;
p是a的地址, *p是a的值
&:取地址
*:解引用

为了加深理解找了个小例子

#include<stdio.h>
int a = 2, b = 3;
int * q;
void fun(int* p)
{
	p = &b;
	printf("%d\n", *p);
}
int main()
{
    q = &a;
    printf("%d\n",*q);
    fun(q);
    printf("%d\n",*q);
    return 0;
}

上述例子输出为:
2
3
2
分析:q本身存的是a的地址,输出2,将q赋值给子函数的形参p后,p也指向了a,然后在函数内部又将p指向了b,于是函数内部输出3,但是不影响外部的q,q依然指向a,依然输出2。

那么现在来修改一下fun的内部代码

#include<stdio.h>
int a = 2, b = 3;
int * q;
void fun(int* p)
{
	*p = b;//注意这里已经修改了!!!
	printf("%d\n", *p);
}
int main()
{
    q = &a;
    printf("%d\n",*q);
    fun(q);
    printf("%d\n",*q);
    return 0;
}

此时的输出为:
2
3
3
分析:q本身存储了a的地址,输出2,将q赋值给子函数的形参p后,p也指向了a,此时和上一个fun不一样的是,在函数内部对p解引用,并且将p指向的位置的值更改为b,就是将内存中存储的a变成了b,于是函数内部输出3,执行完之后回到主函数,q依然指向a那个位置,但此时内存里已经没有a了,a变成了b,所以输出的是3。

二级指针

int a;
int * p;
p = &a ;
int **q ;
q= &p ;
p是a的地址, * p是a的值
q是p的地址, * q是p的值,是a的地址, **q是 * p的值,是a的值;
在这里插入图片描述
二级指针的使用要比一级指针更加谨慎,尤其是在指针强转的时候,一不小心就指向了奇怪的地方。。。。
比如下面这段定义:
uint32_t x = 10 ;
uint32_t * a ;
a = &x ;
CustomType **b = (CustomType **)&a ;
如何通过b去输出变量x的地址和值?
首先a=&x,a的值就是x的地址, * a就是x的值
而b存储的是指针a的地址,即&a,且做了一次强制类型转换。
则*b就是对二级指针解引用,得到a,即&x,由此得到了x的地址,但由于a是uint32_t类型的指针,再对b进行解引用之后需要强转成uint32_t类型的指针,即(uint32_t *)(*b),这样才能精准的访问到a的值,即x的地址,再在前面加一个 * 就能访问到x的值了。
这里有个会弄混的误区,就是直接对b进行(uint32_t *)强转,没有做解引用,这其实是对a的地址的强制转换,并不是对a的强制转换,而a才是那个需要强制转化得到的指针。

指针数组和数组指针

其实听名字就能分清楚的,但总是说着说的会乱掉。。。。定义的时候一个不注意就是一团乱。。。。

指针数组

一个由很多个指针组成的数组。本质上是个数组,只是其中的元素是指向别的空间的指针。
例如由10个int型指针组成的数组:int *p[10];
这时候需要对数组中的每个指针规定指向,就可以访问到其他不同的内存空间。

数组指针

本质上是一个指针,指向一个数组。
例如一个指向长度为10的int型数组的指针:int( *p)[10];
这里需要注意的点就是,注意区分指向数组首元素的指针,和指向数组的指针,虽然值是一样的,但是前者储存的是数组首元素的地址,和数组无关。而后者存储的是数组的首地址,是和整个数组相关联的

下面举个例子:

指向数组首元素的指针:
int *p1 = b;
int a[5] = {1, 2, 3, 4, 5};
int *p2 = a;
p2这个指针仅仅只是指向了第一个元素,并非整个数组。本质上和p1一样
这里给p2+1再解引用,得到的是数组a中第二个元素的值,即 *(p2+1)=2;

指向数组的指针:
int temp[5] = {1, 2, 3, 4, 5};
int (*p)[5] ;
p = &temp;
这里要注意,temp是数组里第一个元素的地址,&temp才是整个数组的首地址
万万不可写成p=temp,二者虽然在值上一致,但含义完全不同,编译也会报错的
如果我们需要得到数组的第二个元素的值,按照上面普通指针的写法就完全错误了,因为这里的p+1,偏移量是整个数组而不是一个数组元素, 正确的写法应该是 * (*p+1)

指针的长度和指针类型和偏移量

指针的长度只和处理器的位数有关,指的是sizeof的结果,在32位系统中就是4字节,64位系统中就是8字节,和它的类型无关。
而指针加减1的操作和类型有关,比如一个int型指针,p+1的偏移量是4字节,而double类型的偏移量就是8字节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值