|
发表于 2010-6-20 15:11:50
|
显示全部楼层
1# VBProFan
只要你能理解指针是个什么玩意儿,这道题目就会很简单了。
我以前在和学弟学妹交流时,总会向他们强调:指针也仅仅是一种数据类型而已,只不过在多数编辑器内部的存储方式恰巧和整型一样而已(理论上它的确可以保存成浮点型)。而且指针这种数据类型在语义层次上支持加法和减法。只不过很多C语言教材都把指针作为单独一章来讲解(并且通常放置在书本的后半部分),给初学者潜意识里造成它和以前所学的数据类型不同的感觉。
当然,指针的加减法不能简单地理解为数值操作,比如:
- int a = 0;
- int *p = &a;
- p = p + 1;
复制代码
其中 p = p + 1 这一句里的“1”不能简单地理解为数值“1”,而应该理解为“一个单元”,而整句话的意思就是“该指针指向下一个单元”。
我们知道C语言里不同的基础类型所占用的空间大小不同,比如在Visual C++的实现中,long型是4个字节,char型是1个字节。这意味着,long型指针指向下一单元时,会前进4个字节;而char型指针指向下一单元只会前进1个单元,其他类型依此类推。
这也就是为什么“指针既然是一种数据类型,但却要给每个类型设置一个对应的指针”的原因,它是在告诉编译器这类指针一个单元的步长。
回到这道题目上,我们只看 int a[5] = {1, 2, 3, 4, 5};。大部分新手可能只注意到5个量:a[0]、a[1]、...、a[4],但在语义上来说,“a”也是一个量,它的类型是“长度为5的整型数组”,在Visual C++上,它占用空间大小是20个字节(可以用sizeof(a)得到)。
因此,原题中“int *ptr = (int *)(&a + 1);”这句话看起来诡异,但按照上面的分析,其实无法就是对这种“长度为5的整型数组”类型的指针做了一次加法操作,即前进1个单元(20个字节),最后把结果的类型强制转换为“整型指针”。
到目前为止,我们已经能给出一个理论上的答案了,这段程序的运行结果是给出“a”后面一个单元上的内容。那它到底是输出什么内容呢?以我所掌握的知识来说:这个结果是不确定的!因为C语言标准文档里没有规定程序运行时内存空间的分配方案,因此不同的厂商在实现的编译器在处理这个问题上都各不相同。
一个比较常见的方案是按照源代码中定义的顺序重下往上分配空间。比如题目中 a, b, c, ptr 都是局部变量,因此分配在“栈空间”里,c是第一个变量,因此在栈底,接着是a、b以及 ptr。在这种模式下会输出“7”(即c[0]的值)。
但这个问题还会牵涉到“操作系统的虚拟内存管理”、“编译器的优化”、“空间对齐”等诸多问题。比如你用GCC编译时,是否开启O2优化选项,产生的结果是不一样的。因此,确切地说这道题是条件不足,并不能给出唯一的结果。
关于指针和数组更详细的讨论,欢迎参看我以前的文章:《编程村一日游》http://blog.csdn.net/redraiment/archive/2010/01/10/5171510.aspx |
评分
-
查看全部评分
|