免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 11931 | 回复: 5
打印 上一主题 下一主题

C/C++数组名与指针区别深入探索(转) [复制链接]

论坛徽章:
0
1 [报告]
发表于 2006-12-17 12:50 |显示全部楼层
To smallchilli

转载文章请注明出处。这不仅是对作者的尊重,也是对自己的尊重。

----------------------------------------------------

在网上经常看到类似的文章,一上来先把国人数落一顿(他们很少对外国人这样做),想以此表明自己的叙述是多么的正确。我倒是发现:那些指责别人的人,往往是自己并没有真正理解所提问题的人,往往也在自觉或者不自觉地犯着概念上的错误。

比如,一个对数组的普遍的误解就是:数组变量不能被改变,是因为数组被转换为一个指针常量。上面文章的作者就持这种观点。其实真正的原因是因为数组是一个不可被改变的左值。在下面的帖子中我说明了“数组是常量”这种观点为什么是错误的:
http://bbs.chinaunix.net/viewthr ... p;extra=&page=2

在上面的文章中,作者想竭力证明“数组名不是指针”。其实这个问题是不需要证明的,因为数组和指针毕竟是两种不同的类型,不存在谁替代谁的问题。

想这样做的人其实还不明白一个基本的事实:数组对象本身(一个左值)的类型是数组,数组对象的值(一个右值)是一个指针。因此,数组对象是按照数组类型解释还是指针类型解释是由其在程序中所处的上下文环境决定的。“数组名不是指针”是不错的,但是也不要否认“数组名可以作为指针使用”,毕竟作为指针使用才是在程序中使用数组的主要方式。

数组可以作为两种类型(分别是数组和指针)使用,使数组成为一种特殊的类型,也使得人们对数组概念的理解容易产生偏差,即使是对一些有丰富经验的程序员来说也是这样,因为要真正了解数组,需要对表达式、左值和右值等概念有清醒的认识。所幸的是:即使不了解上面的概念,一般人也能正确地使用数组。

论坛徽章:
0
2 [报告]
发表于 2006-12-17 13:00 |显示全部楼层
To zx_wing

>> 1、数组名不是指针。数组名代表一个地址,这个地址是数组中第一个元素的地址。

当你说数组名一个地址的时候,这就意味着它已经是一个指针了,因为 C/C++ 总所说的地址都是指针类型,而不仅仅是一个简单的数字。

>> 2、指针是一个变量,用来存放地址。

为什么要认为指针是一个变量呢?指针也可以通过表达式的计算求值得到,比如 &a(a是一个变量)就是一个指向对象 a 的指针。

>> 另外,楼主最后没有说明为什么数组名做为参数传递的时候会变成指针(想当年某高人写的一本xx指南里说数组名做参数时退化成指针,到现在我都还不明白什么叫退化)。

“退化”其实就是数组类型转换为指针类型的另外一种通俗的说法,因为在此转换的过程中数组的长度信息被丢弃了,所以形象地称这种转换为“退化”。退化(decay)最初并不是由国人提出的。

其实,数组退化、即数组转换为指针并不仅仅发生在函数参数中,在一般情况下也发生:
  1. int a[10];
  2. int* pa = a;  // 这里,数组 a 退化为 int* 指针。
复制代码

跟函数中的情况不同的是:上面的这种退化现象是“测量”不出来的,即不要妄图指望用 sizeof(a) 的结果来证明数组 a 退化为指针的现象没有发生过。

[ 本帖最后由 whyglinux 于 2006-12-17 13:22 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2006-12-17 14:08 |显示全部楼层
>> C/C++ 总所说的地址都是指针类型”,那是从语言的观点来看,而我是从计算机的角度来说的。

角度不同,有些概念的解释也不同。当讨论 C 语言的时候,还是把概念的范畴限定在语言的范畴中吧,否则就乱套了。你说呢?

>> &a准确的说不是产生指针,而是产生一个地址(也就是一个数字)

&a 的结果是一个 pointer,这是 C 或者 C++ 标准的规定。&a 这个表达式的结果是指针类型,而且是一个右值,所以不需要内存空间来存储这个地址。

“指针需要在栈上占用存储空间”的正确性仅仅对于指针变量而言,而且仅仅限于非静态指针--对于静态指针和动态分配的指针,其内存的分配并不是在栈上。

论坛徽章:
0
4 [报告]
发表于 2006-12-17 17:12 |显示全部楼层
>> 我习惯这样说:在堆上分配了一块内存,指向的这块内存的指针在栈上。 在堆上分配的我都叫它内存,不叫指针哈,嘿嘿,还是我们看问题的角度不同

那静态指针呢?也在栈上?

论坛徽章:
0
5 [报告]
发表于 2006-12-17 17:39 |显示全部楼层
To zx_wing

很高兴讨论问题。你觉得我说的有问题的地方就指出来,这很正常,不存在什么“挑”不“挑”的问题。

关于你上面问的这个问题,只要明白了 C 或者 C++ 标准把对象的存储期间划分为三类,就能明白我说的了。直接引用原文吧:

An object has a storage duration that determines its lifetime. There are three storage durations: static, automatic, and allocated.

其中,“allocated”就是通常说的“动态分配”。

论坛徽章:
0
6 [报告]
发表于 2006-12-17 18:35 |显示全部楼层
>> 关键是我只把“指针变量”称做指针
>> 呵呵,讨论了这么久,看来是我对指针的定义比较狭义,你的比较广义。

这应该就是问题的关键了。C/C++ 中的指针是广义的,只要结果是指针类型的表达式(当让包括变量)都可以称为指针。

然而在标准制定之前,人们确实通常仅仅称指针变量为指针(pointer)。例如 Brian W. Kernighan by Brian W. Kernighan 的名著《The C Programming Language》中就是这么定义指针的:

A pointer is a variable that contains the address of a variable.

其实,在现代 C 语言中,这个定义已经不准确了。但是,由于这本书的影响如此之深远,所以很多人和很多资料上都是这么认为指针的,要注意区分这种情况。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP