纬图虚拟仪器论坛

 找回密码
 立即注册
搜索
查看: 16158|回复: 13

一个变态的C语言面试题

[复制链接]
发表于 2012-11-26 14:53:11 | 显示全部楼层 |阅读模式
int a[3]={1,2,3};
int *p = (int *)(&a +1);
*(p -1) = ?


回复

使用道具 举报

 楼主| 发表于 2012-11-26 15:37:41 | 显示全部楼层
本帖最后由 wdluo 于 2012-11-26 16:08 编辑

我们一步一步来解析下这个题目
1、a是一个包含3个int型数据的数组,a同时也是指向这个数组首地址的指针,假设a[3]的起始地址是0x40000000,那么a的值就是0x40000000,我们用下图表示。

数据
数据对应的物理地址
Bit[32:24]
Bit[23:16]
Bit[15:8]
Bit[7:0]
0x40000000
Bit[32:24]
Bit[23:16]
Bit[15:8]
Bit[7:0]
0x40000004
Bit[32:24]
Bit[23:16]
Bit[15:8]
Bit[7:0]
0x40000008
0x4000000C

在0x40000000地址处存放的是a[0]变量,也就是1。
在0x40000004地址处存放的是a[0]变量,也就是2。
在0x40000008地址处存放的是a[0]变量,也就是3。
2、&a是取a的地址,所以&a就是一个指向数组首地址的数组指针,其值也是0x40000000,但是它指向的数据类型是a[3]这个数组的首地址。
3、&a+1,由于我们知道&a是指向a[3]这个数组的指针,所以对这个指针加1,在物理地址上应该加上这个指针所指对象占用的物理地址空间数,假设int数据类型是占用4字节地址空间,那么a[3]就占用3*4=12字节的地址空间,因此&a+1应该等于0x40000000+12=0x4000000C,也就是说&a+1所指向的物理地址是0x4000000C。
4、(int *)(&a +1)是对&a+1这个指针进行强制数据类型转换,也就是将这个指向a[3]数组的指针强制转换为一个指向int类型的指针,刚才我们知道&a+1的物理地址是0x4000000C,所以p就是一个指向int类型的指针了,而且其值为0x4000000C。
5、*(p -1)是取指针所指向的数据,由于p是指向0x4000000C的,而且指向的类型被强制转换为int型,因此对它做减1操作后其值就变为0x40000008了,再对它进行取数据操作最后得到的数据就是0x40000008这个地址单元所存放的int数据类型的数据,也就是a[3]数组的最后一个数据3,也就是说这个题的答案是3!
怎么样?看似简单的题目包含的东西多吧?

回复 支持 反对

使用道具 举报

发表于 2012-11-26 22:31:52 | 显示全部楼层
以为是1,结果错了,用visual c++证实确实是3,看来要好好学习啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-11-26 23:19:12 | 显示全部楼层
ming1006 发表于 2012-11-26 22:31
以为是1,结果错了,用visual c++证实确实是3,看来要好好学习啊

点评

我也以为是1  发表于 2013-1-4 10:34
回复 支持 反对

使用道具 举报

发表于 2012-11-26 23:40:35 | 显示全部楼层
wdluo 发表于 2012-11-26 23:19

选1的情况应该是int *p = (int *)(a +1);一个符号就天壤之别啊
回复 支持 反对

使用道具 举报

发表于 2012-11-26 23:41:52 | 显示全部楼层
还发现题目的int a[3]={1,2,3};改成int a[]={1,2,3};是一样的

回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-11-27 09:29:07 | 显示全部楼层
ming1006 发表于 2012-11-26 23:41
还发现题目的int a[3]={1,2,3};改成int a[]={1,2,3};是一样的

当然是一样的,这两种声明方式本来就是一样的
回复 支持 反对

使用道具 举报

发表于 2012-11-27 09:59:13 | 显示全部楼层
wdluo 发表于 2012-11-27 09:29
当然是一样的,这两种声明方式本来就是一样的

也就是说他会自己计算好长度,而不是不知道数组的长度
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-11-27 10:11:51 | 显示全部楼层
ming1006 发表于 2012-11-27 09:59
也就是说他会自己计算好长度,而不是不知道数组的长度

它会根据你初始化的数据定义长度,但是在使用的时候编译器是不检查数组长度的
回复 支持 反对

使用道具 举报

发表于 2012-11-27 10:22:51 | 显示全部楼层
wdluo 发表于 2012-11-27 10:11
它会根据你初始化的数据定义长度,但是在使用的时候编译器是不检查数组长度的

如果是二维数组不知道怎么简单的指向下一行呢?如char a[][3]={1,2,3,4,5,6,7,8,9};
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-11-27 10:58:03 | 显示全部楼层
ming1006 发表于 2012-11-27 10:22
如果是二维数组不知道怎么简单的指向下一行呢?如char a[][3]={1,2,3,4,5,6,7,8,9};

这个编译器也可以通过列的长度自动确定行数,但是不能通过行数确定列数,比如 char a[3][]={1,2,3,4,5,6,7,8,9};这样就不行
回复 支持 反对

使用道具 举报

发表于 2012-11-27 12:38:25 | 显示全部楼层
wdluo 发表于 2012-11-27 10:58
这个编译器也可以通过列的长度自动确定行数,但是不能通过行数确定列数,比如 char a[3][]={1,2,3,4,5,6, ...

恩,试验了下,二维数组的情况下int *p = (int *)(&a +1);为9,int *p = (int *)(a +1);为3,int *p = (int *)(a[0] +1);为1


回复 支持 反对

使用道具 举报

发表于 2013-5-16 21:56:26 | 显示全部楼层
楼主们。领教了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|纬图虚拟仪器

GMT+8, 2024-12-22 11:30 , Processed in 0.556781 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表