打印
[信息]

问个C语言问题

[复制链接]
3437|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qwer0145|  楼主 | 2016-10-24 16:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr2 = (int *)((int)a + 1);
printf("%x\n",  *ptr2);

运行结果是 2000000,这结果是怎么来的?
沙发
sonicll| | 2016-10-24 16:36 | 只看该作者
本帖最后由 sonicll 于 2016-10-24 16:37 编辑

应该是小端法存储的问题,a[0]和a[1]在内存里应该是 01 00 00 00 02 00 00 00这样存的,ptr2指向的地址对应的数据是 00 00 00 02,所以按照小端法int型来读取就变成0x02000000

使用特权

评论回复
板凳
qwer0145|  楼主 | 2016-10-24 18:58 | 只看该作者
sonicll 发表于 2016-10-24 16:36
应该是小端法存储的问题,a[0]和a[1]在内存里应该是 01 00 00 00 02 00 00 00这样存的,ptr2指向的地址对应 ...

还不是很明白,我试了试+2 结果 20000,+3 结果 200,+4 结果 2,+5 结果 3000000

使用特权

评论回复
地板
稳稳の幸福| | 2016-10-24 19:06 | 只看该作者
这个牵涉到存储和指针的问题。

使用特权

评论回复
5
戈卫东| | 2016-10-24 20:22 | 只看该作者
你吧指针转换成整数运算后又转换成指针。
如果不能理解这样做的后果是什么就不要这么弄。

使用特权

评论回复
6
技术小小兵| | 2016-10-24 20:28 | 只看该作者
qwer0145 发表于 2016-10-24 18:58
还不是很明白,我试了试+2 结果 20000,+3 结果 200,+4 结果 2,+5 结果 3000000

0x0000 0000         01 00 00 00
0x0000 0004         02 00 00 00
0x0000 0008         03 00 00 00
0x0000 000C         04 00 00 00

假设a=0x00000000,(int)a,a就是0,(int)a+1就是1,指向地址0x00000001的int型数据(连续4个byte)就是 00 00 00 02,小端存储,就是0x02000000;
如果变成+2,a就是等于2,指向地址0x00000002地址的int型数据就是 00 00 02 00,
然后自己计算吧。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
离源 + 1 正解
7
xmshao| | 2016-10-24 20:29 | 只看该作者
这里本来a是个地址,或者说是指针。 但你 (int)a 强转后的结果便是一个整型数据了,它再加1就是只加1而不是加4了。

如果你写成 (int *)(a + 1); 那又不一样了,此时加1则是加1个INT宽度4,此时读得数据时a[1];

使用特权

评论回复
8
皈依| | 2016-10-24 22:07 | 只看该作者
本帖最后由 皈依 于 2016-10-24 22:10 编辑

这是个好题,首先你得分大端模式还是小端模式,即高位数据存储在高位地址还是低位地址。
int *ptr2 = (int *)((int)a + 1);
首先假设是小端模式,即高位地址对应高位数据。
首先(int)a将首地址强制转换成整形,加1的话就是向右移32/4位,因为地址是32位的 a+1是偏移32位,而(int)a+1就是偏移8位。
回到小端模式,a指向的内存里32位分别是:0000,0001,0000,0000,0000,0000,0000,0000,转化为u8就是01 00 00 00
以此类推,第二位就是02 00 00 00 ,第三位就是 03 00 00 00等等等等。
所以(int *)((int)a + 1);就是指向01 00 00 00中的第一个00的32位地址,对应的数据是:00 00 00 20,由于是小端模式,所以打印出来是02 00 00 00
以此类推,+2就是 00 02 00 00 +3就是00 00 02 00,+4就是 00 00 00 02 +5就是03 00 00 00
整体地址对应的内存里面的数据:
01 00 00 00   02 00 00 00  03 00 00 00  04 00 00 00  05 00 00 00
右移之后不够的用后面内存里面的东西补上

大端模式的推理一样。
纯粹手打。。。望散分。。。

使用特权

评论回复
9
qwer0145|  楼主 | 2016-10-25 08:05 | 只看该作者
谢谢各位的回答,看来要看看数据存储模式了

使用特权

评论回复
10
qwer0145|  楼主 | 2016-10-25 08:28 | 只看该作者
皈依 发表于 2016-10-24 22:07
这是个好题,首先你得分大端模式还是小端模式,即高位数据存储在高位地址还是低位地址。
int *ptr2 = (int  ...

明白了,谢谢了

使用特权

评论回复
11
pener| | 2016-10-25 09:01 | 只看该作者
看来要随手加括号

使用特权

评论回复
12
皈依| | 2016-10-25 13:52 | 只看该作者

客气

使用特权

评论回复
13
Thethree| | 2016-10-25 19:13 | 只看该作者
像这种编程的用法在单片机编程中常用吗

使用特权

评论回复
14
linqing171| | 2016-10-26 06:17 | 只看该作者
个人风格问题。不存在常用不。

使用特权

评论回复
15
linqing171| | 2016-10-26 06:18 | 只看该作者
arm下,指针对不齐,有问题,

使用特权

评论回复
16
大熊寻找很幸福| | 2016-10-27 11:37 | 只看该作者
这个代码还可以顺便用来判断系统的存储的大小端模式,哈哈哈~

使用特权

评论回复
17
hgjinwei| | 2016-10-27 12:31 | 只看该作者
这代码如果在ARM指令下,会死得很惨

使用特权

评论回复
18
Larm1| | 2016-10-27 14:28 | 只看该作者
种东西,面试时经常会见到...

使用特权

评论回复
19
zyj9490| | 2016-10-29 20:52 | 只看该作者
超出了A的取值范围,把RAM不知的地方取进来了。

使用特权

评论回复
20
zyj9490| | 2016-10-29 20:56 | 只看该作者
sizeof(a)=10,sizeof(a[0])=2,明白这点,就问题就明白了。这样的指针写法不好。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

51

帖子

3

粉丝