数组的首地址,数组名取地址,地址的强制转换为int

#include <stdio.h> 

int main()
{
int a[5]={7,8,9,10,11};
int *ptr1=(int *)(&a+1);
int *ptr2=(int *)((int)a+1);

printf("%d\n",&a);
printf("%d\n",(int)a);
printf("%d,%d\n",ptr1,ptr2);
printf("%d,%x\n",ptr1[-1],*ptr2);


return 0;
}

输出结果:

1245036
1245036
1245056,1245037
11,8000000
Press any key to continue
结果怎么会是这样的呢???特别是&a,(int)a的值都是1245036 那么分别加以后怎么结果不是一样的???还有就是*ptr2的值(十六进制)是:80000这个值不是随机数呢??(我开始认为是的,但实际不是的),让我们来一起分析一下:

首先我们要知道a[5]={7,8,9,10,11};的意思:在内存中开辟一个数组大小是: sizeof(int)*5=4*5=20个字节(一个整形占4个字节),那么数组名a的值就是这片内存单元的首地址

我们看到printf("%d\n",&a);printf("%d\n",(int)a);输出的结果:1245036 1245036,我们可以知道&a是上面内存单元的首地址,(int)a是把首地址转换成int的数据。

int *ptr1=(int *)(&a+1); 其中&a+1,不是简简单单的加一,而是加上数组的大小(表示指针移到数组内存单元的最后的下一个单元地址)为什么???那是因为系统在内存中(具体的说应该是栈中)为数组分配一个连续大小为20字节的大小,并把首地址赋值给数组名a,那么&a+1就是表示这个内存的下一个地址,这个加一不是我们平时说的整数1,而是数组的大小即1245036+20=1245056,那么指针变量ptr1就是指向此内存单元,那么*ptr表示地址为1245056单元的内容,而ptr1[-1]等价于*(ptr1-1),ptr1-1即先把指针后移一个,不是指向数组的最后一个元素吗??,那么*(ptr1-1)不就是数组最后的值吗???即11,十六进制是b

而int *ptr2=(int *)((int)a+1); 就是在1245036+1=1245037,这又是为什么???原因很简单那是因为:(int)a表示的把数组地址即内存单元的编号转换成整数,那么此时的(int)a+1加一相当于加一个整数!!

注意1245037在于数组第一个和第二个元素地址中间(可以数组数组的第一元素和第二个元素的地址分别是:1245036 1245040),那么*ptr2的值就是第一个元素的二进制和第二个元素的二进制的组合:那我们看看数组第一元素和第二个元素的二进制是:

7的二进制:0000 0000 0000 0000 0000 0000 0000 0111

8的二进制:0000 0000 0000 0000 0000 0000 0000 1000

那么*ptr2的值就是从7的二进制的第二个字节开始数四个字节(即取7的后三个字节和8的第一个字节):

0000 0000 0000 0000 0000 0111 0000 0000

注意在内存是先放低字节,然后是高字节,那么计算的时候的到过来即:0000 0000 0111 0000 0000 0000 0000 0000 0000

那么对应的十六进制是:0080000,即80000

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值