指针的本质

       说起指针,不少人认为指针是C/C++语言中尽量避免使用的东西,乃至把它当做潘多拉魔盒。但是作为一种比C# JAVA要低级一点的语言,其优势也就在于能够使用指针。指针为何会有很多人希望不用它是因为它容易出错,而一旦出错,要么指向不可用的内存直接崩溃,要么将把别人的一些正确的东西弄错了,搞出莫名其妙的结果。

       其实指针并不可怕,要理解指针,首先要内存说起。就不扯到高端的64位处理器,拿我们用得最频繁的32位系统说起吧。指针的值的范围是多少呢?在32位系统里,sizeof(void*)其实长度刚好是4,也就是说如果把它强转成一个long对象,那么刚好匹配的值与long相同,也就是0~4294967294,刚好就是4G,而32位内存寻址最大值也是4G。事无凑巧,指针其实就是一个值对应的内存寻址中的地址。当我们定义一个变量 不管是局部变量还是 new一个出来,都会有其地址,也就是可以用一个指针的值来保存它,指针也可以通过取值符号*来拿到其对应的值。

      这个时候,问题来了,指针类型可是多种多样的,不仅仅只有一种指针,比如 void*  int* float*等,这个其实和取值计算有关,只有告诉编译器你的指针是什么类型,编译才能够算出你要取的值究竟有多大该怎么表示,最终找到内存地址,把内存地址中的数据,转换成已知类型传递给程序。并且指针的运算符号也是基于此,比如:

int* i = new int;
printf("%u\n", i);
++i;
printf("%u\n", i);
--i;

delete i;


输出结果是:

3362432
3362436

而不是

3362432
3362433

指针的值 多了4 而不是1 ,而4刚好是== sizeof(int)

只有代码:

char* i = new char;
printf("%u\n", i);
++i;
printf("%u\n", i);
--i;
delete i;


输出结果才是:

4149496
4149497

因为1 == sizeof(char)


因此我们可以通过类型强转 把指针类型转换成不同类型,来达到灵活挪动内存位数,也可以依靠这个来做到遍历二进制数据。


指针另外一个让人头疼的,无疑就是 指向指针的指针,比如 int** pp;

指向指针的指针也叫双重指针,其存的值就是一个指针对象的地址。要知道当我们定义 int* p = NULL;的时候,这个指针p其实也有自己的地址,以为指针其实也是一种数据类型,与float int等一样,都是变量,也就一样拥有地址和值。不过指针的值就是另外一个值的地址而已。


这种东西主要用途是在于 从函数中传递指针


比如我们希望写一个函数,从中可以拿到我们分配好的一块内存的首地址,但是返回值已经被其他功能占用,这个时候需要通过从传递的参数中把值返回回来。

我们也知道 函数中传递参数其实是会把参数进行值的拷贝

比如

void func(int a){ a = 3;}  如果代码这么写

int i = 2; func(i); 这个时候执行完结果i依旧是2,因为func(i)执行的时候 a会被当做一个局部变量一样执行 a = i 的逻辑,然后再执行a = 3

这个时候a变成什么样与i无关。 因此 要改变i 得写成 void func(int* a){ *a = 3;} 这个时候 执行func(&i),可以把i变成3。


同理,当要传递一个指针出来的时候 我们可以用类似的方式 void func(int** ptr){   ... ;   *ptr = pArray;} 来获得pArray[0]的地址到外面


int* p;

func(&p); 

//p == pArray


指针还一个易错的,就是指针值拷贝,其实就是地址复制。这种操作其实是很危险的。

我们C++代码,有一个原则,谁创建的谁销毁。而这种值拷贝会直接破坏这个原则。


比如我int* p  = new int[3];

int* q = p;

这个时候,p如果执行了delete[] p; 如果q没有得到通知清除为0,那么就会变成一个野指针,指向不可引用的内存。如果取其值将造成内存越界崩溃。

而更可怕的是,内存越界并不一定会崩溃,当后面其他对象被创建的时候,如果刚好又把这个地址变成可用的,那么q就指向了另外一个未知的地址,而你调用它对它进行操作,可能带来的结果不是崩溃,而是诱发其他地方出现崩溃或者数据异常。这个就非常难查。


所以,指针是个好东西,但是一定要用好,废品往往是被用废的好东西。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值