Chinaunix

标题: 讨论下这个题目,请不要先编译 [打印本页]

作者: jiony    时间: 2009-05-07 10:45
标题: 讨论下这个题目,请不要先编译
#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("%x,%x",ptr1[-1],*ptr2);
return 0;
}

作者: flyingtime    时间: 2009-05-07 10:53
ptr1的值不确定
ptr2 = 8
作者: dreamice    时间: 2009-05-07 10:54
ptr1[-1] =11
&a+1是a的地址+1,可以看作是二重数组的下一个地址了,即相当于a[5]的为止了,退回一个位置,应该就是11这里了。
第二个不太清楚
作者: daybreakcx    时间: 2009-05-07 10:58
第一个是十进制的11,因为&a+1被当作了把a当作二维数组,指向第二行第一个,ptr1[-1]就是第一维的最后一个
第二个是十进制的8
作者: flyingtime    时间: 2009-05-07 11:00
ptr1 跟字节对齐有关吧,有人实测过ptr1、ptr2吗?
作者: langue    时间: 2009-05-07 11:25
第一个没有争议,就是 b。

现在看第二个。

32-bit, LE:
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00

32-bit, BE:
  00 00 00 07 : 00 00 00 08 : 00 00 00 09 : 00 00 00 0A : 00 00 00 0B

16-bit, LE:
  07 00 : 08 00 : 09 00 : 0A 00 : 0B 00


可以看出:

32 位小端字节序,结果是 8000000h;
32 位大端字节序,结果是 700h;
16 位小端字节序,结果是 800h。




[ 本帖最后由 langue 于 2009-5-7 11:28 编辑 ]
作者: bsdc    时间: 2009-05-07 11:30
原帖由 jiony 于 2009-5-7 10:45 发表
#include  
int main()
{
int a[5]={7,8,9,10,11};

int *ptr1=(int *)(&a+1);

int *ptr2=(int *)((int )a+1);

printf("%x,%x",ptr1[-1],*ptr2);
return 0;
}


第一个,&a虽然和a值一样,但+1的概念跨越不一样,+1等于加5*4个字节,刚刚跑出数组范围,然后被转为int *,ptr1[-1] = *(ptr1 - 1),后退一个int, 即4个字节,得到11,即0xb

第二个,a即为a数组首元素地址, 地址在32位机器上是4字节,那么+1字节后,又强转为int *, 取4字节地址,在*ptr2的时候,跨越a[0],a[1], a[0]取3字节,a[1]取1字节,根据小尾数的规则:
a[0] = 0x00000007; a[1] = 0x00000008;
           07 00 00 00             08 00 00 00
然后拼成 00 00 00 08  即为 0x08000000
大尾数的话相应就为 00 00 07 00 即为  0x700

[ 本帖最后由 bsdc 于 2009-5-7 12:01 编辑 ]
作者: hellioncu    时间: 2009-05-07 11:31
可能会总线错误吧
作者: daybreakcx    时间: 2009-05-07 11:31
还跟小端表示和大端表示有关系,7楼的图表意很清晰

[ 本帖最后由 daybreakcx 于 2009-5-7 11:34 编辑 ]
作者: bobozhang    时间: 2009-05-07 11:33
原帖由 langue 于 2009-5-7 11:25 发表
第一个没有争议,就是 b。

现在看第二个。

32-bit, LE:
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00

32-bit, BE:
  00 00 00 07 : 00 00 00 08 : 00 00 00 09 : 00 00  ...


强烈支持
作者: gz80    时间: 2009-05-07 11:34
32-bit, LE应该是这样吧
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00
作者: langue    时间: 2009-05-07 11:34
标题: 回复 #8 hellioncu 的帖子
确实有这个可能,看编译器的实现和 CPU 类型了。
作者: langue    时间: 2009-05-07 11:36
标题: 回复 #11 gz80 的帖子
已经转化为整型,所以不是加 sizeof(int),而是直接在数值上加 1。前面有人提到总线错误的问题,就可能出现在这里。
作者: gz80    时间: 2009-05-07 11:40
原帖由 langue 于 2009-5-7 11:36 发表
已经转化为整型,所以不是加 sizeof(int),而是直接在数值上加 1。前面有人提到总线错误的问题,就可能出现在这里。

Sorry 我错了,呵呵
作者: file3    时间: 2009-05-07 11:41
bu dong
作者: dreamice    时间: 2009-05-07 12:33
原帖由 langue 于 2009-5-7 11:25 发表
第一个没有争议,就是 b。

现在看第二个。

32-bit, LE:
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00

32-bit, BE:
  00 00 00 07 : 00 00 00 08 : 00 00 00 09 : 00 00  ...


版主这个是编译后看到的地址么?
作者: bsdc    时间: 2009-05-07 13:51
那不是地址,是数组里的数据
作者: dreamice    时间: 2009-05-07 14:47
原帖由 bsdc 于 2009-5-7 13:51 发表
那不是地址,是数组里的数据


我知道,我得意思是编译后看到的地址对应的数据存储?
作者: daybreakcx    时间: 2009-05-07 15:16
原帖由 dreamice 于 2009-5-7 14:47 发表


我知道,我得意思是编译后看到的地址对应的数据存储?

应该是运行时所对应的内存中的数据吧
作者: jiony    时间: 2009-06-03 15:35
标题: 回复 #7 bsdc 的帖子
不明白:
1.既然&a虽然和a值一样,那为何(&a+1)和(a+1)的理解不同
2.对数组名进行强制类型转换的作用是什么?即int a;
作者: liuhengloveyou    时间: 2009-12-07 11:52
原帖由 langue 于 2009-5-7 11:25 发表
第一个没有争议,就是 b。

现在看第二个。

32-bit, LE:
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00

32-bit, BE:
  00 00 00 07 : 00 00 00 08 : 00 00 00 09 : 00 00  ...


顶这个!
作者: koolcoy    时间: 2009-12-07 11:55
utu: utu: utu: utu: utu: utu: utu: utu: utu: utu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu: :outu:
作者: ecjtubaowp    时间: 2009-12-07 12:17

作者: churchmice    时间: 2009-12-07 12:19
标题: 回复 #20 jiony 的帖子
1.虽然值一样,但是类型不一样
2.为了让指针移动一个字节的长度
作者: wolfired    时间: 2009-12-07 13:02
b
8000000

==================

&是取址操作
&a自然是得到一个指针,关键是得到的这个指针是什么类型!

作个对比

int i;

那么&i的类型就是int*

所以&a的类型应该是int (*)[5]

所以&a + 1跨过了20个字节,指向了11的下一个字节

ptr1[-1]自然就是b

===================
先看下内存的情况(小端,地址左到右,上到下增大)
07 00 00 00
08 00 00 00

a是一个指针,(int)a就是把指针转换成int, + 1就到了紧跟07后面的那个地址,再转回int* ,进行解引用操作就得到8000000

===================
总结,看代码还真是马虎不得!惭愧!

[ 本帖最后由 wolfired 于 2009-12-7 13:13 编辑 ]
作者: huangwei0413    时间: 2009-12-07 13:34
ptr2没有按照4字节对齐,发生段错!
作者: benjiam    时间: 2009-12-07 14:45
7l
作者: cnzhaopeng    时间: 2009-12-07 15:19
标题: 回复 #1 jiony 的帖子
可能会出现 Segmentation fault. 因为平台是不是32的原因。
作者: churchmice    时间: 2009-12-07 17:12
标题: 回复 #28 cnzhaopeng 的帖子
sun 32平台就是bus error
作者: llry    时间: 2009-12-08 14:08
原帖由 langue 于 2009-5-7 11:25 发表
第一个没有争议,就是 b。

现在看第二个。

32-bit, LE:
  07 00 00 00 : 08 00 00 00 : 09 00 00 00 : 0A 00 00 00 : 0B 00 00 00

32-bit, BE:
  00 00 00 07 : 00 00 00 08 : 00 00 00 09 : 00 00  ...


是不是结果多写了几个0啊?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2