一道面试题,求输出结果

时间:2022-06-23 11:31:30
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);
int *ptr2 = (int *)((int)a+1);
cout << ptr1[-1] << '\t' << *ptr2;
被问倒了,第一个结果是5还能理解,第二个是一个很大的数,为什么啊?谁知道吗

27 个解决方案

#1


指向未知内存的数?

#2


int强制类型转换改变了a的值..

#3


把地址转换成整形+1  栈地址都很大的。。。

#4



不记得是在那本书上看过这个了 !
嘿嘿 !

a  ptr2
01   [color=#FF0000]00   00   00, 02   [/color]00   00   00,   

所以 *ptr2 = 0x 02 00 00 00;

#5


菜鸟表示关注中

#6



抱歉不清晰 !

建议你去测试下 a, 和 ptr2 ; 看看他们的地址的关系!


a    ptr2

01    00    00   00  ,  02    00   00   00,

所以 *ptr2 = 0x 02 00 00 00 ;

#7


int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下,所以这个值是无效值
 cout << ptr1[-1] << '\t' << *ptr2; 
输出值为5 和 一个任意值

#8


int *ptr2 = (int *)((int)a+1);
指向的是*a往后移动一个字节的位置,这是没有意义的操作,所以强制转化为int类型后变成了一个很大的数,如果写成int *ptr2 = (int *)((int)(a+1));就是指的数组第二个元素

#9


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下……


你的无效值,让我很不安!

#10


引用 9 楼 modicum_lf 的回复:
引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&amp;amp;a+1); //表示下一个数组,也可以说是a[5]
int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a……


小端模式下 是0x2000000
大端模式下 是0x100

怎么会是个无效值呢 ?

#11



01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


#12


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。

呵呵,误解了楼主,这个解释正确...

#13


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下……


第一个ptr1 = (int *)(&a + 1); //加1 加的是整个数组的长度也就是 + sizeof(a)*1, 大家可以理解,也可以说表示a[5]。。。

而ptr2 = (int *)((int)a + 1);//这里的加1 加的是数值 1(也就是1个字节),因为把他强制转换为整型。问题就是加整型1怎么理解。a[0]有4个字节,加了一个字节后就是后3个字节和a[1]的前一个字节组成了四个字节。输出*ptr2所以结果如何就看你的机器是大端模式还是小端模式了。
内存如下布局
01 00 00 00 02 00 00 00
a[0]      a[1] 
小端的话a[0]后3个和a[1]的前一个字节就组成了,0X02000000
大端...................................,0x00000100

#14


学习。。。。

#15


ptr2所指的是a[0]的第二个字节开始连续4个字节

01 00 00 00,02 00 00 00,小端模式!ptr2 所指的4个字节: 00 00 00 02,*ptr2的值为0x02000000

00 00 00 01,00 00 00 02,大端模式!ptr2 所指的4个字节:00 00 01 00,*ptr2的值为0x00000100


#16



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

转换成int型,加1以后再转换成int*

#17


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


这个是正解 所以你在windows 用 vc 结果是  0x2000000

#18


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


同意11楼,答案。

#19


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


正解,楼主结贴吧。

#20


VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要写连自己也预测不了结果的代码!

#21



//代码最清楚了,您请看
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
char *p;
int x=0x12345678;
p=(char*)&x; //低地址单元
if (*p==0x12)
{
cout<<"大端"<<endl;
}
else if (*p==0x78)
{
cout<<"小端"<<endl;
}
//一般你电脑是8086的pc,小端模式
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);//这个a+1,加的1是数组类型,就是加5个字节
int *ptr2 = (int *)((int)a+1);//ox 00 00 00 02
cout << ptr1[-1] << '\t' << *ptr2;
cout<<endl<<"推测:"<<(int)0x02000000<<endl;//把上面的地址,依据小段方案,就是02 00 00 00
return 0;
}

#22


引用 20 楼 zhao4zhong1 的回复:
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要写连自己也……

经常看到这样的回复 TT

#23


学习了 

#24


学习~~~

#25


搞不明白。 一道面试题,求输出结果

#26


mark

#27


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解……
+1为什么是加了一个数组的长度?

#1


指向未知内存的数?

#2


int强制类型转换改变了a的值..

#3


把地址转换成整形+1  栈地址都很大的。。。

#4



不记得是在那本书上看过这个了 !
嘿嘿 !

a  ptr2
01   [color=#FF0000]00   00   00, 02   [/color]00   00   00,   

所以 *ptr2 = 0x 02 00 00 00;

#5


菜鸟表示关注中

#6



抱歉不清晰 !

建议你去测试下 a, 和 ptr2 ; 看看他们的地址的关系!


a    ptr2

01    00    00   00  ,  02    00   00   00,

所以 *ptr2 = 0x 02 00 00 00 ;

#7


int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下,所以这个值是无效值
 cout << ptr1[-1] << '\t' << *ptr2; 
输出值为5 和 一个任意值

#8


int *ptr2 = (int *)((int)a+1);
指向的是*a往后移动一个字节的位置,这是没有意义的操作,所以强制转化为int类型后变成了一个很大的数,如果写成int *ptr2 = (int *)((int)(a+1));就是指的数组第二个元素

#9


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下……


你的无效值,让我很不安!

#10


引用 9 楼 modicum_lf 的回复:
引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&amp;amp;a+1); //表示下一个数组,也可以说是a[5]
int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a……


小端模式下 是0x2000000
大端模式下 是0x100

怎么会是个无效值呢 ?

#11



01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


#12


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。

呵呵,误解了楼主,这个解释正确...

#13


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解下……


第一个ptr1 = (int *)(&a + 1); //加1 加的是整个数组的长度也就是 + sizeof(a)*1, 大家可以理解,也可以说表示a[5]。。。

而ptr2 = (int *)((int)a + 1);//这里的加1 加的是数值 1(也就是1个字节),因为把他强制转换为整型。问题就是加整型1怎么理解。a[0]有4个字节,加了一个字节后就是后3个字节和a[1]的前一个字节组成了四个字节。输出*ptr2所以结果如何就看你的机器是大端模式还是小端模式了。
内存如下布局
01 00 00 00 02 00 00 00
a[0]      a[1] 
小端的话a[0]后3个和a[1]的前一个字节就组成了,0X02000000
大端...................................,0x00000100

#14


学习。。。。

#15


ptr2所指的是a[0]的第二个字节开始连续4个字节

01 00 00 00,02 00 00 00,小端模式!ptr2 所指的4个字节: 00 00 00 02,*ptr2的值为0x02000000

00 00 00 01,00 00 00 02,大端模式!ptr2 所指的4个字节:00 00 01 00,*ptr2的值为0x00000100


#16



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

转换成int型,加1以后再转换成int*

#17


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


这个是正解 所以你在windows 用 vc 结果是  0x2000000

#18


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


同意11楼,答案。

#19


引用 11 楼 modicum_lf 的回复:
01 00 00 00 , 02 00 00 00, 小端模式! 0x00 02 00 00

00 00 00 01 , 00 00 00 02, 大端模式! 0x00 00 01 00

*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。


正解,楼主结贴吧。

#20


VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要写连自己也预测不了结果的代码!

#21



//代码最清楚了,您请看
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
char *p;
int x=0x12345678;
p=(char*)&x; //低地址单元
if (*p==0x12)
{
cout<<"大端"<<endl;
}
else if (*p==0x78)
{
cout<<"小端"<<endl;
}
//一般你电脑是8086的pc,小端模式
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a+1);//这个a+1,加的1是数组类型,就是加5个字节
int *ptr2 = (int *)((int)a+1);//ox 00 00 00 02
cout << ptr1[-1] << '\t' << *ptr2;
cout<<endl<<"推测:"<<(int)0x02000000<<endl;//把上面的地址,依据小段方案,就是02 00 00 00
return 0;
}

#22


引用 20 楼 zhao4zhong1 的回复:
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要写连自己也……

经常看到这样的回复 TT

#23


学习了 

#24


学习~~~

#25


搞不明白。 一道面试题,求输出结果

#26


mark

#27


引用 7 楼 namelij 的回复:
int a[5] = {1,2,3,4,5};
 int *ptr1 = (int *)(&amp;a+1); //表示下一个数组,也可以说是a[5]
 int *ptr2 = (int *)((int)a+1);//int(a)+1 先将a所在的地址转换成10进制,然后加1,也就是说ptr2指向的是 a的十进制地址+1处,注意,如果是(int)a+4的话,恰好是a[1],所以加1这块你理解……
+1为什么是加了一个数组的长度?