最浅显易懂的 C++指针 学习(含代码分析)

指针:变量的地址。
那地址是什么?首先了解内存编址。

计算机内存是一块存数据的空间,由一系列连续的存储单元组成,每个单元格表示1bit,每八个bit表示一个字节byte。内存寻址的最小单元是一个字节。也就是说,每个byte有一个编号,根据编号就可以找到这个地址。
把这些编号连起来,就是内存的地址空间。这地址空间的大小就和电脑是32位还是64位有关如果是32位,表示cpu支持32位地址空间,即232byte=4*210*210*210=4GB(B表示字节的意思)。而指针是保存地址的,指针必须能表示地址空间最大的地址,因此32位系统,指针是32位(4byte),64位系统,指针是64位(8byte)

因为不同数据类型大小不一样具体,如char是一个字节,short是2个字节,int是四个字节,因此不同类型的指针在寻址的时候,偏移量不一样,取数据的大小也不一样。什么数据类型的指针,取数据的大小、偏移量(对指针作加减时)即为该类型的大小。举个例子:

cout<<(int)(((int *)0)+4)<<endl;

上面这个代码会输出什么?16.

首先((int*) 0)是把0转换为int类型的指针,也就是这个指针表示编号为0的地址。紧接着((int*) 0)+4表示这个地址编号移动4个int类型大小的距离,而int类型是4个字节大小,所以指针+1表示移动4个字节大小,+4表示移动4*4个字节大小。因此地址为16,最后再转为int类型输出。为方便理解,见下图:

/byte0123456789101112
int*0123
char*0123456789101112
short*0123456

其中第一行表示内存空间里的地址编号,每个编号有8bit的空间,对于int类型的指针,每个int类型需要4个字节,因此指针的偏移,每次移动的单位为4个字节,(((int *)0)+4)则表示int类型的指针移动4个单位,所对应的地址编号(第一行)即为16。同样道理,如果是int(((char*) 0)+4),则表示地址编号0开始,移动4个char类型大小的单位,则输出为4;同理,int(((short*) 0)+4)为8。

为了更好地理解,再来看一个代码:

    int a = 0x1234;//0x00001234      小端输出 34  12   0    大端输出 0  0  12
    char* p = (char *)malloc(sizeof(a));
    p = (char *)&a; 
    printf("0x%0x\n", *p);
    printf("0x%0x\n", *(p + 1));
    printf("0x%0x\n", *(p + 2));

这里涉及一个大端小端的概念,大端指数据的高位放在低地址,小端指数据的低位放在低地址。以小端为例分析上述代码。
变量a的十六进制表示为1234,因为24=16,所以十六进制一位数占4bit,则两位十六进制才占一个字节。变量a在内存的储存方式如下(假设a的地址为0):

/byte01234
a341200
char* p0123
    char* p  = (char *)malloc(sizeof(a));
    p = (char *)&a; 

这段代码是开辟了四个字节的空间(sizeof(a))=4)给char类型的指针p; 然后让指针指向a的地址.
如上表所示,假设a地址为0,则p为0。由于该指针类型为char,因此它取值和偏移的时候都是以char类型大小为单位进行操作的,也就是*p对p取值时(地址编号为p的数据)只取一个字节的数,根据表可知,地址为0的一个字节内放的数据为34,*(p+1)则为12,以此类推。

如果是大端呢?那就改变一下数据存储方式,高位字节放在低位:

/byte01234
a003412
char* p0123

结果显而易见。


最近面试被问了关于指针的代码改错和分析题。虽然之前了解过,但是没有自己总结,所以在思考的时候容易混乱。借此机会总结一下。
面试的时候我基本思路是对的,但是忘记一个概念,就是计算机内存寻址单元是以字节为单位的;sizeof的输出也是以字节为单位的。这些都是最基础的东西,怎么能忘呢?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值