C++指针详解

前言
今天发现自己对C++了解得还不够深刻,毅然决定重新补充C++指针的知识。一直在论坛里听别人说没有几个人真正的会用指针,我居然怀疑了一下自己,好吧。恶补呗,顺便写篇博客祭奠一下,这篇文章适合非小白看,我只是把容易错的点补充了。

1.数据在内存中是如何存储的

 在编译时就会系统就会给变量分配内存空间,这里有个概念必须理清,就是内存单元地址跟内存单元内容,在编译期间,变量实际上已变成内存单元地址(就0xYYYYY)之类的,然后系统根据地址找到内存单元内容,如定义了变量INT I=100;i的内存单元内容就是100。

这里写图片描述

2.指针和指针变量的概念

  上述查找I的内容是直接寻值,还有一种是间接寻值,即有一种特殊变量是用来存放某个变量的内存单元地址。该特殊变量的值称之为指针(其实某个变量的地址就是指针)。

3.定义指针变量及其概念

 int *pointer_01; 

 上述所定义的指针变量是指向整型数据的指针变量。也就是说,指针变量pointer_1只能指向整型的变量,一般定义指针的形式:基类型 *指针变量名。
 请各位注意,*并不是该指针变量的变量名,在变量名前加*只是为了说明该变量是指针变量。

 我的电脑输出结果为:007FF824---007FF824---100
    int* pointer_01;
    int a=100;
    pointer_01=&a;
    cout<<&a<<"---"<<*pointer_01<<"---"<<pointer_01<<"---"<<&pointer_01;
    \\&是取地址的符号
    \\我的电脑输出结果为:0097F874---100---0097F874---0097F880
每个人运行的结果前两个值都会相同,说明了pointer变量的内存单元内容是a的地址,pointer是变量,所以有自己的内存单元地址,用*引用pointer变量的内存单元内容即可找到真正的值。到这,我回想了一下,我之前确实误解了指针的真正含义,如果不经常用真的很容易把概念混淆。

4.指针作为函数参数

例如:函数Do(int *point_01),定义了变量:int *point_01,i我们调用是传得是地址即point_01,&a等,千万不用传*point_01,因为人家需要的是地址,加*号就指向了a的内容即100了。

5.指针与数组

  1. 指向一维数组的指针

    数组因为内存中是顺序存放的,当指针指向数组某一个位置时,通过加减移动指 针就可以访问数组中的元素,数组名字默认是数组首位的地址。
    例如: int a[5];int *point_01=a;point_01+1==a[1];

  2. 指向二维数组的指针

    用单个指针引用二维数组考虑数组在内存中的存放情况即可。

    #include <iostream>
using namespace std;
int main( )
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;                              //p是基类型为整型的指针变量
for(p=a[0];p<a[0]+12;p++)
    cout<<*p<<endl;
cout<<endl;

system("pause");
return 0;
}
   当用指针数组引用二维数组要注意的是,指针数组的增值是以一维数组为单位,想要任意访问二维数组中任一元素,应该这么写:定义了point_01[n],   用*(*(point_01+i)+j)访问i行j列。
   解析:*point_01+i指向了a[i],在二维数组中显示一维的就是该维的地址,然后用地址+1再用*引用得出值。

6.字符串与指针

   字符指针不同与整形指针,字符指针可以初始化。输出也不一样,具有一定的特殊性,待我慢慢说道。我们先理清一下概念:
   1. 输出指针的内容(即所指向空间的地址)cout<<p<<endl
   2. 输出指针所指的内容(即指针内容所描述地址空间中的内容):cout<<*p<<endl
   指针对于字符的处理却有些特殊,和前面的非字符的指针输出处理要分开理解。

   首先举个例:
   char a='T';
   char *p=&a;
   cout<<p<<endl;
   cout<<*p<<endl;
   第一行会输出T####,  #代表乱码,并不是地址。
   第二行会输出T。

   当时我遇到这种情况和各位一样的懵,p不是存放着地址吗,为什么会T####?很明显已经指向内容了啊,原来是cout的原因,cout操作字符指针的话,它遇到字符地址,就会直接去寻找这个地址所指向的内容,并把它的空间里的机器数按照字符的规则转化成字符输出,直到遇到“\0”这个操作符才停止。所以我们直接输出p的时候,它先输出‘T’然后再继续读取后面的内存空间直到遇到“\0”,显示结果是“T+乱码”。在这里再强化一个概念,地址即指针,牢记。

7.指针数组和指向指针的指针

 指针数组:一般的定义形式为类型名*数组名[数组长度];在这个数组里每位元素都是指针。
 但是我们要区别清楚:
 int *p[4]------这是指针数组。
 int (*p)[4]---------这是数组指针。
 这俩位仁兄长得实在太像,平时我特别容易混淆,但它俩却大不相同。果然,C++都是坑,慢慢填吧。

 指针数组是一个只存放定义类型的指针的数组。

 数组指针是一个指针,只能指向定义类型的数组。

8.指向指针的指针

  我的天,看到这个标题我脑子飞速饶了几圈,妈呀,指针都够烦了,还要☞中☞,要是真想在项目中玩起来,估计得有些修行。

  在理解前面指针数组的基础上,我们再来看指向指针的指针。不说废话,先上到菜。
#include <iostream>
using namespace std;
int main( )
{ char **p;                //定义指向字符指针数据的指针变量p 
char *name[]={″BASIC″,″FORTRAN″,″C++″,″Pascal″,″COBOL″};
p=name+2;                //见图6.23中p的指向
cout<<*p<<endl;          //输出name[2]指向的字符串
cout<<**p<<endl;         //输出name[2]指向的字符串中的第一个字符
}
//输出结果为:
//C++
//C

解析:字符指针数组是一个指针数组,里面的元素name[i]都是指针==地址,数组名name代表该指针数组首元素的地址。name+i是name[i]的地址,所以p=name+2是合法的。指针-指针==地址-地址,这种方法就多级间接访问,下面配个图方便理解。
这里写图片描述

9.指针总结

希望大家认真复习指针,看见下图中的每一个定义要能迅速想起对应的概念
这里写图片描述

10.引用

 顺便说说引用的意思跟引用和指针的区别。

 引用的概念:
 int a;                       //定义a是整型变量
 int &b=a;                    //声明b是a的引用

 引用只是一个变量的别名

 引用和指针的相同点:
 (1)都是指针的概念
  只不过指针的内容是某块内存的地址,引用是某块内存的别名。

  不同点:
1. 指针是一个实体,而引用仅是个别名;

2. 引用使用时无需解引用(*),指针需要解引用;

3. 引用只能在定义时被初始化一次,之后不可变;指针可变;

引用“从一而终” ^_^

4. 引用没有 const,指针有 const,const 的指针不可变;

5. 引用不能为空,指针可以为空;

6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。

7. 指针和引用的自增(++)运算意义不一样;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值