[讨论]《说C·变量》专题,为说明指针,不得不从头来……

BluntBlade 2005-10-12 10:34:55
痛苦,为什么新手们没兴趣研究语法背后的东西呢……

1 引言
编程的目的是计算,而计算要处理的对象是数据。在要使用计算机进行计算工作,首要工作是解决数据的表示、存储和访问问题。所幸二进制数制体系和基于半导体的硬件平台较好地解决了数据的表示和存储问题,我们只要在逻辑上解决数据的访问问题就可以了(访问问题包括读操作和写操作)。
那么在逻辑上,我们如何访问数据呢?程序运行时,相关数据存储于内存之中(本篇假定数据只存储于内存中,其它情况类同),是一种物理存在。想要从逻辑上访问数据,必须设定一种机制将数据的逻辑表示和其物理存在联系起来。从程序设计语言(以下简称语言)的角度来说,就是要使用某种符号来表示数据,这些符号由语言的实现(即编译器、链接器及相关的开发环境等)进行处理以表现其与数据的物理存在的联系。这种符号表示数据的方法与数学中变量的概念非常类似,因此在大多数语言中,均引入“变量”这一概念作为数据的逻辑表示形式。访问变量,即是访问变量中存储的数据。
让我们再做一个小小的概念变换,即“变量”就是一种“对象”。“对象是一块可以检查和存放的内存区”,对象的大小决定了其存储数据的值域范围,而对象的类型决定了定义在它上面的操作集合。通过语言提供的声明符和定义语句,可以很方便地在程序中开辟出对象。因此研究变量,就是研究变量的声明、定义、大小、类型等等……好吧,好吧,下面先讲讲变量的语法。
...全文
1639 69 打赏 收藏 转发到动态 举报
写回复
用AI写文章
69 条回复
切换为时间正序
请发表友善的回复…
发表回复
yongjie_2008_java 2010-05-27
  • 打赏
  • 举报
回复
关于指针还是有点迷糊,所谓的指针和指针变量究竟是怎么回事啊?
hot225dog 2006-01-05
  • 打赏
  • 举报
回复
不停的捞帖。。。

痛苦,为什么新手们没兴趣研究语法背后的东西呢……
----------------------------------------------------
我是新手,楼主是老师?要是我的老师就太好了。有一段时间了,苦于找不到学习材料,目前最想了解和掌握语法实现、结合对应的汇编的C。

语法学了2年不到,我看过的差不多的书中涉及到语法实现都不是深入探讨,于是在茫茫书海和帖海中试图想寻些门道,虽然有些收获,但更重要的是浪费了很多鉴别的时间,经常看帖与系统的学习不合.
而且没有标准的材料也总会主观的去猜想是不是如此云云。。

建议社区成立项目,为了共同的爱好,让高手们系统的讲述市面上很缺的但很必须很实在的东西...

关于楼上几位高手的探讨,我现在根本不能从技术上加以分析,听过一句话:"你会的东西不一定能表达出来,能表达出来的一定是会了",所以说除了技术上的分析表达,其他的表述应该考虑到会的人有以上两种可能.

还有关于标准,很好的理解标准,作为标准的用户,可以更好的运用这个语言.在平时学习操作系统设计或是计算机硬件设计的过程中强烈的感觉到作为现在正在使用的各种标准而言,它是各种方案可能是完全相反的两种实现原理博弈而生的,标准的目的会考虑通用、性能等。所以说现在的标准不是最好的(主观的判断),至少不是每个细节都是最好的,所以希望高手们在探讨的时候多多涉及一些标准之后的,我这个新手也好多多学习,即便看不懂也会顶上的,不为其他的,就因为喜欢他。。。
我也一直认为csdn是国内最好的同类社区之一(貌似语法级问题比较多)。

以上是一个学生一些不成熟的看法,切望点播指正,虽然不能当面沏茶拜师,但一定会心存感激的。。。
kobefly 2005-11-29
  • 打赏
  • 举报
回复
学习
megaboy 2005-11-29
  • 打赏
  • 举报
回复
还得作一个小小的更正:the referenced type指的是"a function type,an object type, an incomplete type。因此,那段话第一句话应该这样说:


指针的类型可以派生于函数的类型、对象的类型或者不完整类型,它们被称为引用类型。

ilovedudu 2005-11-29
  • 打赏
  • 举报
回复
顶!
希望争论之后达成共识!期待中!
whyglinux 2005-11-28
  • 打赏
  • 举报
回复
趁热打铁,再分析一下 K&R 说的这句话:

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

这里的 pointer 显然应该是指针变量(pointer variable)、而不是指针常量(pointer constant)或其它。只有这样解释,这句话才有成立的可能。但是如果直接说“A pointer variable is a variable that ...”有重复之嫌,所以也可能是只说“A pointer is a variable that ...”的一个原因。

另外,即使是把其中的 pointer 解释为 pointer variable,从这句话的后半部分来看也描述得很不全面的。一个指针中存放的只是“the address of a variable”(变量的地址)吗?显然不是这样的。

我在前面说过,在程序中表示对象的方法有两种:通过变量的方法以及通过引用的方法。变量表示对象是通过定义变量来实现的,由于有一个变量名与此对象相关,这个对象是一个有名对象。另外一种创建对象的方法是通过动态内存分配,这样创建的对象是没有名字的,因此不能通过变量直接访问,只能通过引用进行间接访问。然而,这样的对象当然也是有地址的,也可以放到一个指针(变量)中去。

因此,一个指针不仅可以存放变量的地址,也可以存放一个非变量表示的对象的地址。所以,单从 K&R 的这句话来看对术语的界定模糊、对问题的描述不全面,不可以作为规则来使用。

bestlife 2005-11-28
  • 打赏
  • 举报
回复
搬个凳子来看
whyglinux 2005-11-28
  • 打赏
  • 举报
回复
>> 我晕,int *const constant_ptr;不是变量?你怎么学指针的?constant_ptr仍然是一个左值!!!

你说的没错,变量指针和常量指针都是说的指针是变量的情况。发完之后再一看,对我的论点没有支持力。不过,我不是还说了“pointer constant”(指针常量)的情况吗?那又怎么解释呢?

从你引用的标准原文来看,你已经承认了指针是一种类型,对吗?

另外,我一再强调引用文章的时候还要联系注意上下文。先把上面的标准原文引用完整:

A pointer type may be derived from a function type, an object type, or an incomplete
type, called the referenced type. A pointer type describes an object whose value
provides a reference to an entity of the referenced type. A pointer type derived from
the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a
pointer type from a referenced type is called ‘‘pointer type derivation’’.

首先你要明白,标准中的 object 和 function 是区别开来的:函数不是对象,对象也不是函数,Ok ?

从第一句话中可以看出,一个指针类型可以用来表示一个函数的地址、一个对象的地址以及一个非完整类型的地址。Ok ?

而第二句话只是对上述三种情况之一的“对象”进行了描述。那么这句话是说指针类型只(only)描述对象,而不能用来描述函数以及非完整类型吗?答案不是很清楚吗?
fixopen 2005-11-28
  • 打赏
  • 举报
回复
呵呵,拍别人的砖总是很爽的。

但我不想拍砖,我觉得楼主的意思已经表达的很清楚了,意图已经基本达到,能让初学者甚至不是初学者学到一些东西,错误是难免的,一则源于尽量的口语化倾向(这样才容易理解),二则是没有人的知识结构是完美的。

至于 megaboy(飞天御剑流之杀神一刀斩),我觉得简直就是当年的pora的初级版,呵呵,这绝对没有任何贬义,相信大家都记得pora的功力。希望能进一步发展到pora的水平,而不要搞出一些自己没有完全清楚的概念(或者没有办法完全说清楚的概念)来批评别人。
megaboy 2005-11-28
  • 打赏
  • 举报
回复
现在我要出去办事,回来再给你来个大洗脑!!
megaboy 2005-11-28
  • 打赏
  • 举报
回复
指针还有非变量的吗?是的,还有“constant pointer”(常量指针)。
------------------------------------------------------------
我晕,int *const constant_ptr;不是变量?你怎么学指针的?constant_ptr仍然是一个左值!!!
megaboy 2005-11-28
  • 打赏
  • 举报
回复
对于这个领域,C/C++标准是最终裁决。
--------------------------------------
你这句话说得没错,C标准是最终裁决。但是谁一直在引用标准?你有这样做过吗??你有引用过哪怕一丁点标准来证明你自己吗?但是,首先要讨论的问题是:你看过标准吗?


我也知道,对于自己信仰的东西,很难容得别人来说三道四,因为打破自己的信仰是一件非常痛苦的事。
------------------------------------------------------------
你的信仰难容别人说三道四,偶很理解。但是,不是说因为那是自己的信仰,就是正确的!谁经历过这样的痛苦?你吗????我就经历过这样的痛苦!实话跟你说,当初我初学C的时候,学的就是潭那两本破书《C语言程序设计》和《C++语言程序设计》,我以前,跟你现在一样,也是认为指针就是地址,但随着对C逐步深入了解,真正拿起一本标准来阅读,发现根本不是这么回事!这其中的痛苦,你知道吗?


关于你以后的解释,通篇都是对我本人的否定,而没有对我的论点进行否定,所以不和你争论。
------------------------------------------------------------------------------
请你指出来,哪一点是针对你本人的??为什么你不能争论?因为你无法反驳来自标准与C发明人的根据!这是不容怀疑的!


可以看出你到现在还在把理解为“指针”就是指“指针变量”,不承认有“指针类型”这个概念。如果你知道了C/C++中还有指针类型,那么你就明白了什么是指针变量、什么是指针常量、什么是常量指针。
关于2,google的搜索结果已经说明了你的“所谓指针变量这个概念,其实是中国人自己杜撰出来的”。如果你不相信这个结果,也好,请拿出你的证据证明你的这个论断。
-----------------------------------------------------------------------
这个根据,早就说了,C89/C99没有pointer variable或者variable of pointer这个概念,标准里面一直说的,只有pointer。

什么是pointer type?偶就给你说说标准里面是怎么说的:

A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’.

标准已经清楚地表明了,a pointer type描述的是一个对象!
whyglinux 2005-11-28
  • 打赏
  • 举报
回复
再给一个证据。

我又查了一下C99标准,查找“pointer variable”,没有任何结果。查找“variable pointer”倒是找到了一个(p115, 6.7.5.1.3),下面是原文:

EXAMPLE The following pair of declarations demonstrates the difference between a ‘‘variable pointer to a constant value’’ and a ‘‘constant pointer to a variable value’’.
const int *ptr_to_constant;
int *const constant_ptr;
The contents of any object pointed to by ptr_to_constant shall not be modified through that pointer, but ptr_to_constant itself may be changed to point to another object. Similarly, the contents of the int pointed to by constant_ptr may be modified, but constant_ptr itself shall always point to the same location.

这里特别指出了“variable pointer”(变量指针)。什么?指针还有非变量的吗?是的,还有“constant pointer”(常量指针)。不仅如此,还有“pointer constant”(指针常量,可在标准中查到原文),比如我们熟悉的 NULL 就是。
megaboy 2005-11-28
  • 打赏
  • 举报
回复
再补充一点,其实pointer type那段话已经表明了,pointer is a object。就是那一句:

A pointer type describes an object whose value provides a reference to an entity of the referenced type.

这里所说的object,并不是pointer所指向的东西,而是pointer本身!
whyglinux 2005-11-28
  • 打赏
  • 举报
回复
To megaboy(飞天御剑流之杀神一刀斩)

关于我的第一条,你为什么不给出结果。希望你认真查一下。
1. 建议你查一下C或者C++标准,有没有“pointer type”,这个问题不就清楚了吗?

可以看出你到现在还在把理解为“指针”就是指“指针变量”,不承认有“指针类型”这个概念。如果你知道了C/C++中还有指针类型,那么你就明白了什么是指针变量、什么是指针常量、什么是常量指针。

关于2,google的搜索结果已经说明了你的“所谓指针变量这个概念,其实是中国人自己杜撰出来的”。如果你不相信这个结果,也好,请拿出你的证据证明你的这个论断。

关于你以后的解释,通篇都是对我本人的否定,而没有对我的论点进行否定,所以不和你争论。只有你对我提出的论点感兴趣的时候,我才有兴趣和你作进一步的讨论。

我也知道,对于自己信仰的东西,很难容得别人来说三道四,因为打破自己的信仰是一件非常痛苦的事。但是幸好我们讨论的问题不是思想领域上的,而是在C/C++领域。对于这个领域,C/C++标准是最终裁决。
megaboy 2005-11-28
  • 打赏
  • 举报
回复
更抽象地说,pointer应该是个对象。这样在概念上可以统一起来,解释起来也较“指针变量”容易得多。
----------------------------------------------------------
这样的观点就正确了。pointer就是一个object,而address不是一个object,是一个rvalue,因此pointer不是address。
megaboy 2005-11-28
  • 打赏
  • 举报
回复
“函数不是对象”这是一种过时的观点,在C89发布之前,不少编译器的确不把函数看作一个对象,但c89 committee纠正了这个观点。也许你从来没有想过为什么C89/C99在函数名是一个右值的情况下仍然允许&func这种东西?ANSI及ISO在rationale of c99(当然还有rationale of c89)中解释了这一点:

6.5.3.2 Address and indirection operators

Some implementations have not allowed the & operator to be applied to an array or a function. (The construct was permitted in early versions of C, then later made optional.) The C89 Committee endorsed the construct since it is unambiguous, and since data abstraction is enhanced by allowing the important & operator to apply uniformly to any addressable entity.

这段话说明了&func的意义,并不是对函数名取地址,而是对一个函数对象取地址,也正因为如此,&func所代表的地址值才跟func一样。K&R也在其书第二版中表达了函数是一个对象的意思:

4.3 External Variables

A C program consists of a set of external objects, which are either variables or functions.


不过,在这里讨论函数是否一个对象属于题外话,我们要谈的,不是指针所指向的东西是不是一个对象,而是指针本身是不是一个对象!

我认为你并没有弄明白C89/C99关于pointer type那段话的意思,这段话的大意是:指针的类型被称为引用类型,它可以派生于函数的类型、对象的类型或者不完整类型。它描述一个对象,这个对象的值提供一个对引用类型实体的引用,因此,它有时候又被称为指向T类型的指针。这段话所表明的是:对于一个指针p,如果它指向一个整数对象,那么这个指针的类型就叫整数指针,如果它指向的对象是一个函数,那么它就叫函数指针,如此类推。而不是你所理解的pointer is a type!

megaboy 2005-11-28
  • 打赏
  • 举报
回复
2. 建议在 google 中输入“pointer variable”,看看有几百万条目跟这是有关的。再在中文网页中查找“指针类型”,其条目数不过才区区几十万。然后再看看你的结论。
---------------------------------------------------------------------
一个问题的根据是在google中搜索条目,哪个条目多就是哪个对么?简直是天大的笑话,用一句不客气的话说:简直乱放屁!



3. 注意:函数的返回值是一个临时生成的“无名”对象,跟表达式的值是一样的。“无名对象”顾名思义就是没有名字来表示的对象,怎么可能是用“变量”来表示呢。能用变量表示的对象不会是无名对象吧。
.........................
因此,这并不是说“里面所写的概念、语法、定义、规定通通都不算数”(不过不排除这种可能性),你还要结合上下文正确理解它们才行。
----------------------------------------------------------------
我敢说,你连标准都没见过。什么是object,什么是value of expression、什么是lvalue、什么是rvalue你都还没弄清楚。自己先去找本C89/C99看看,然后逐一回答标准是怎么给上述四个东西定义的!



如果没有上下文的话,“你是一个人”这句话根据强调的重点不同可以有多种理解。但是无论怎样,你不能根据这句话判断“我是学生”或者“我是教师”的真伪。正如我在上面所说的:“指针”可以指类型、对象(变量)以及值(内存地址)等多种概念。
-----------------------------------------------------
自己先去翻翻K&R这本书的上下文。连书都没看过,谈什么书?



另外,即使是把其中的 pointer 解释为 pointer variable,从这句话的后半部分来看也描述得很不全面的。一个指针中存放的只是“the address of a variable”(变量的地址)吗?显然不是这样的。
----------------------------------------------------------------
我真怀疑你连K&R是谁都不知道。你这句话是在表明这样一个信息:C的发明人把自己发明的东西写错了!!



我在前面说过,在程序中表示对象的方法有两种:通过变量的方法以及通过引用的方法。变量表示对象是通过定义变量来实现的,由于有一个变量名与此对象相关,这个对象是一个有名对象。另外一种创建对象的方法是通过动态内存分配,这样创建的对象是没有名字的,因此不能通过变量直接访问,只能通过引用进行间接访问。然而,这样的对象当然也是有地址的,也可以放到一个指针(变量)中去。
----------------------------------------------------------------------
一看你写“有名对象”、“无名对象”就知道你所持的是那种关于对象的谬论。自己先翻翻标准是怎么给“对象”下定义的!
whyglinux 2005-11-27
  • 打赏
  • 举报
回复
To BluntBlade(无锋之刃·回炉再造)

我只是提醒你我注意到的一些问题,至于你接不接受那是你的事。

1. 等待着你的新版文字。

2. 数据类型是什么。有一个简单的规则,就是:把你声明语句中的变量名去掉,剩下的就是这个变量代表的类型。可以按照这个规则来检验 int* pi; 以及 double* pd;是否是相同的指针类型。

>> void意味着零长度

void 是一种不完整数据类型,即它的长度不能确定。如果void是零长度的话,表明它的长度已经确定,与不完整数据类型的定义矛盾。

>> 最后,所谓“pointer variable”,也只不过是Chinese English而已。
“pointer variable”不是Chinese English,在 google 中搜一下就可以明白了。

>> 更抽象地说,pointer应该是个对象。

不,如果把 pointer 理解为是 pointer type 就好办了。
whyglinux 2005-11-27
  • 打赏
  • 举报
回复
1. 建议你查一下C或者C++标准,有没有“pointer type”,这个问题不就清楚了吗?

2. 建议在 google 中输入“pointer variable”,看看有几百万条目跟这是有关的。再在中文网页中查找“指针类型”,其条目数不过才区区几十万。然后再看看你的结论。

3. 注意:函数的返回值是一个临时生成的“无名”对象,跟表达式的值是一样的。“无名对象”顾名思义就是没有名字来表示的对象,怎么可能是用“变量”来表示呢。能用变量表示的对象不会是无名对象吧。

4. 如果我说:你是一个人,按照你的意思,这根本不能说明你是一个人,是不是非得要这样说:你只是一个人,才能说明你是一个人???

如果没有上下文的话,“你是一个人”这句话根据强调的重点不同可以有多种理解。但是无论怎样,你不能根据这句话判断“我是学生”或者“我是教师”的真伪。正如我在上面所说的:“指针”可以指类型、对象(变量)以及值(内存地址)等多种概念。

在比如:“小花是一只猫”,我对朋友说“小花是我的好朋友”,那么并不矛盾吧。如果这时朋友在我耳边叫嚣“小花不过是一只猫而已”,那你说他是什么意思呢?

因此,这并不是说“里面所写的概念、语法、定义、规定通通都不算数”(不过不排除这种可能性),你还要结合上下文正确理解它们才行。
加载更多回复(49)

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧