总结对指针的一些看法~~~~

c/c++中的指针一般是指指针变量,它与普通的变量不同的是他能根据指针变量的类型通过*来重新解析指针变量的值,比如 :

int i=3;

int *p=&i;

p=&i是给指针变量赋值,对于i编译器根据变量i的类型(int),在内存中划出了4个字节的空间&i~&i+3,以后对i的操作会映射到&i~&i+3这个字节中,比如i=4;编译器会根据编译时所获得类型信息,将4存储到&i~&i+3内存中。编译器给变量的赋值过程跟指针的解引(*)用过程是相似的。上面p=&i;是把i的地址值赋给p,也就是说p的值是编译器分配i变量对应的内存的起始地址值,现在p的类型是int*,当进行*p操作时,编译器认为p的值是某个int类型变量在内存的地址,于是编译器会从p的值对应的内存开始,往下涵盖四个字节,把这四个字节的内存里的数据按照一定的方式取出。指针变量与普通的变量的不同之处也在于此,指针变量能控制对内存数据的解析方式,如果

int i=3;

char *p=(char*)&i;

p的值还是i的首地址,但*p的内容不一样了,由于是char*现在*p只是i的首地址内存的数据。

 

所以对于指针变量有两点是至关重要的,首先是指针变量的值,然后是它的类型也就是它对指针变量值的解析方式,搞明白指针变量这两点基本对指针变量比较从容了~~~~

 

再谈一下数组和指针,一维数组如 int a[10]={0},那么编译器会在内存开辟10*sizeof(int)的连续空间,其中a用来标示这块连续内存的首地址,然后对a[0],a[1].....的访问自动回被转化为*(a+0),*(a+1)....指针形式的访问,因此可以认为a的值是一个编译期就确定下来的常量,默认被解析成对应类型的指针变量的一个值,所以可以赋给对应类型指针变量。因此像

int a[10]={0};

int b[10];

b=a;

这样的语句是编译器所拒绝的,因为编译器要靠b的值,来寻址b[0],b[1]...所以不能修改b的值。另外对于像b[0],0[b]在编译器眼里都会被解析成*(b+0),所数组下标可以为负数,但要注意越界。


  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[10]={0};
  6.     0[a]=10;
  7.     cout<<a[0]<<endl;
  8.     int  *p=a;
  9.     p+=1;
  10.     cout<<(-1)[p]<<endl;
  11.     cout<<p[-1]<<endl;
  12.     system("pause");
  13.     
  14. }

 

对于二维数组,他们在内存也是连续的,如int c[10][10],c也可以认为是一个常量默认解析成一个(*)[10]类型,一个指向数组的指针变量的值。可能有人会问为什么不解析成一个二级指针变量的值,道理很简单比如如下代码:

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[10][10]={10};
  6.     int **p=(int**)a;
  7.     cout<<*p<<endl;
  8.     system("pause");
  9.     **p=1;
  10.     
  11. }

a的值可以强制赋给p,但是*p时会把a对应的内存开始涵盖四个字节的数据取出,解析成一个int*变量的值,此时程序还没有问题*p的值是a[0][0](0x0000000a)的值,但**p操作会从地址值0x0000000a开始涵盖四个字节内存取其中数据组成一个int变量的值,而对0x0000000a访问,很容易非法,故程序挂掉。

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[2][2]={1,2,3,4};
  6.     int (*p)[2]=a;
  7.     cout<<**p<<endl;//->a[0][10]
  8.     cout<<*p[1]<<endl;//->*(*(p+1)+0)->a[1][0]
  9.     int *q=(int*)a;//验证二维数组在内存布局也是连续
  10.     for (int i=0;i<4;i++)
  11.     {
  12.          cout<<q[i]<<endl;
  13.     }
  14.     system("pause");
  15.     
  16. }

 

ps:个人见解,如有错误望不吝指教。(未完)

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值