指针问题,问了N个人还没明白,100分求助
int a[5]={1,2,3,4,5};
int *ptr=(int *)((&a)+1);
printf("%d,%d",*(a+1),*(ptr-1));
问题点数:100、回复次数:22Top
1 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-10-28 11:01:15 得分 0
关键是那个强制转化~Top
2 楼mu_yang(穆扬)回复于 2006-10-28 11:01:25 得分 0
2,5Top
3 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-10-28 11:17:42 得分 30
一道笔试题不理解
silver6 | 25 十一月, 2005 23:36
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
int *ptr=(int *)(&a+1); //指向整个数组末尾
int *ptr=(int *)(a+1); //指向a的下一个元素
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
cout<<*(a+1)<<endl; output:2 没有什么费话~
cout<<*(ptr-1)<<endl; output :5
因为 int *ptr=(int *)(&a+1);
这里是(&a +1) 而非 a+1
&a的类型是数组,所以加1的话,系统会认为加一个a数组的偏移,即5个int
&a+1就是首地址+1
主要是(int*)做了操作,具体什么操作也不是很了解。等高手回答。
如果
&a0x0012ff6c ""
则
&a+10x0012ff6d ""
这里
int *ptr=(int *)(&a+1);
ptr的地址和(&a +1)的地址并不相同
等待高手回答(int *)做了什么操作
&a[0] 才是首地址。
&a是指向首地址的指针。
事实证明:
*(a+1)就是a[1],*(ptr-1)就是a[4]
执行结果是2,5
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
,&a可以认为是整个数组的地址,因此不能单纯的用首地址+1。
1.int * 是强制转换为int型指针。
2.对于int a[5]={1,2,3,4,5};a就是数组首地址。a+1是首地址+1. a 等价于&a[0].
3. &a不是首地址,可以看作是整个数组的指针。&a+1是 a[5]后面的地址.
&a+1≠a+1
废话少说;接:2,5
int a[5]={1,2,3,4,5};
//
// &a 指向是 a[5]的类型, &a + 1指向下一个a[5]类型,等同于指向第6(索引为5)个int
// int *ptr = (int*)(&a + 1) 强制转换指针为int*
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1)); //ptr - 1 指向上一个int,即索引号为4的整数
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5];
而指针加1要根据指针类型加上一定的值,
不同类型的指针+1之后增加的大小不同
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
int *ptr=(int *)(&a);
0040105B lea eax,[ebp-14h] ;a[0]的地址
0040105E mov dword ptr [ebp-18h],eax
int *ptr=(int *)(&a+1);
0040105B lea eax,[ebp] ;这里比上边增加了14h,即20个字节
0040105E mov dword ptr [ebp-18h],eax
&a是数组指针,其类型为 int (*)[5];
同意,谭浩强的c语言编程里讲的很清楚!Top
4 楼mumutingyu(木木)回复于 2006-10-28 11:49:03 得分 10
关键时对于指针加法的理解,是移动指针到该类型的下一个上。&a+1时中是对&a进行加1,而&a是数组的指针,所以+1应该是移动到数组最后也就是a[4]的下一个位置上了。
下面int *ptr=(int *)((&a)+1);也就是说ptr是指向a[4]的下一个int型指针。
所以(ptr-1)应该是指向a[4]的int型指针,所以*(ptr-1)=a[4]=5成立Top
5 楼Jokar(贪睡鼠)回复于 2006-10-28 11:54:28 得分 0
&a: 行指针 :)Top
6 楼chinese_zmm(信誉第一)回复于 2006-10-28 11:59:07 得分 0
int *ptr=(int *)((&a)+1);//&a+1相当于&a是一个2级指针a[0][5],它加一的偏移量是5,而
*(&a)+1的偏移量才是一。Top
7 楼kookworm()回复于 2006-10-28 12:57:18 得分 10
a是一维数组名,所以&a就是以定义的一维数组a做为一个存储单元,由于数组a有5个整形元素,占10个字节,这样&a+1就相当于一次移动10个字节,即移到了数组后的第一个字节。而(int *)又将以数组a为一个单元的指针类型,转化为了以整形为一个单元的指针类型(每移动一次为2个字节),结果使得ptr-1指向了数据的最后一个元素Top
8 楼swimmer2000(时间是用来浪费的,所以每当我做了一点事都觉得很自豪)回复于 2006-10-28 14:54:24 得分 0
int *ptr=(int *)((&a)+1); //&a是一个二级指针,加1后谁都不知道会有什么结果.Top
9 楼jie00677(jie)回复于 2006-10-28 15:05:52 得分 0
运行一下看看几个关键变量的变化规律就应该可以
分析一下原理了,可惜在网吧,没办法运行,有空看看吧Top
10 楼jixingzhong(瞌睡虫·星辰)回复于 2006-10-28 15:42:35 得分 50
int a[5]={1,2,3,4,5};
int *ptr=(int *)((&a)+1);
printf("%d,%d",*(a+1),*(ptr-1));
================
a+1 的结果是明显的,
得到的是指向第二个元素的指针, 所以结果输出2,
下面说一下第二个式子:
a 是数组,
对数组名字取地址后, 得到是一个指向一个5个元素数组的指针,
然后这里 (&a)+1 表示指针下移一个 “元素”,
注意, 这里的元素是一个5元素数组, 相当于是指向了 a 的第六个元素,
(这里越界溢出了,但是 C 中没有越界保护,只要没有非法操作, 那么程序继续运行)
也就是说, ptr 初始化为指向了 a 的第六个元素!!
然后有一个强制转换 int *,
这里就把一个 指向 5 元素数组的指针, 变成了一个指向 int 的指针,
这个变化导致的结果就是 指针步长变化了,
一个 int 指针, ptr-1 表示退后一个元素位置,
注意, 现在 ptr 的类型是 int 指针, 退后一个 int 元素, 就是指向a第五个元素,
结果就是输出了 5Top
11 楼jixingzhong(瞌睡虫·星辰)回复于 2006-10-28 15:45:08 得分 0
关键就是 指针类型和它对应的步长!
对指针 +1 -1 是移动指针“元素长度”距离,
一个 int 指针ptr, -1 就是退后一个 int 元素位置;
而一个 指向5元素数组 的指针(楼主若还是不清晰,请看 指向数组的指针部分内容)
移动一个元素就是移动一个 数组长度空间,
或者理解为是一个 2维数组 的行指针也可以 ...Top
12 楼left_zxp(专逃课的左手)回复于 2006-10-28 20:58:30 得分 0
象int a[i][j]中一样,&a[i][j]是int *[j],即是一个行指针,对它的操作是以j*sizeof (size)为单位的Top
13 楼skkcpp()回复于 2006-10-29 00:02:55 得分 0
我觉得是 2,2Top
14 楼gzlyb(冰风)回复于 2006-10-29 00:44:05 得分 0
这里的高手解释得很清楚
lz应该满意了Top
15 楼todototry(来csdn,学会扯淡了...)回复于 2006-10-29 00:57:42 得分 0
markTop
16 楼yutongjun108(指南针)回复于 2006-10-29 08:28:48 得分 0
markTop
17 楼zhongfusong()回复于 2006-10-29 08:58:18 得分 0
a的类型可以认为是int[5],所以&a + 1,就增加5个int的地址,就指向a[4]的下一个int 地址
但由于p是int *,所以p-1只减小一个int类型的地址Top
18 楼ppx3200(知之为知之,不知为不知!)回复于 2006-10-29 10:55:10 得分 0
非常的清楚了。MARKTop
19 楼gxh9314(什么时候结贴呀!!!!)回复于 2006-10-29 11:20:24 得分 0
dingTop
20 楼zjbirdman()回复于 2006-10-29 12:25:14 得分 0
markTop
21 楼lsd1025()回复于 2006-10-29 13:02:28 得分 0
wanfustudio这位已经讲得太清楚了,
这个问题我完全同意他的讲法Top
22 楼anchor720(菜鸟)回复于 2006-10-31 19:55:42 得分 0
mark
Top




