免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: pmerofc
打印 上一主题 下一主题

[C] 以其昏昏,使人昭昭? [复制链接]

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
181 [报告]
发表于 2010-04-14 15:49 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
182 [报告]
发表于 2010-04-14 15:55 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
183 [报告]
发表于 2010-04-14 16:02 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
184 [报告]
发表于 2010-04-14 16:04 |只看该作者
shan_ghost:
   怎么牵扯到"白马非马“了,跨度好大,我们还是把思维限定计算机科学里面好了,天马星空类的思维方式实在不利于讨论。
标示符在c语言中是一个定义规则,可以用来定义变量,结构名和函数名等等
至于变量数目:
int a;
int *b= &a;
这里面当然有两个变量,一个整型变量,一个整型指针变量。
我不认为是你说的两个标示符和(关联/代表)一个变量。
具体可参考编译原理书中介绍的上下文无关文法定义部分。
如果你没时间讨论那就继续看lz的原帖吧

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
185 [报告]
发表于 2010-04-14 16:09 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
186 [报告]
发表于 2010-04-14 16:30 |只看该作者
本帖最后由 shan_ghost 于 2010-04-14 16:38 编辑

呵呵,看来很多人还是不了解C++新引入的引用概念啊。

int &j=i

注意这里的&并不是取地址,它的意思是声明一个int型的引用,并将它初始化为i所指的变量。于是新的标识符j就和旧的标识符i含义一模一样了。

——————————————————————————————————————————————

而int *j=&i 则表示:
int *j声明了一个指针,这个指针的值等于“标识符i所关联的那个变量的地址”——这个操作 假定 了变量必然是和内存相关联的。

但在实际实现中,如果j没有实际用到,或者在某段代码中没有用到,那么编译器完全可以把变量i暂时放到ax中,并认为ax中的才是变量i——这可以大大加快程序运行速度。

只要在需要用j或其他指针来访问内存中那个变量i之前,同步ax到j所指向的数据,那么变量i就可以同时得到寄存器加速的福利,同时又不会失去“关联到某个内存地址时所应有的表现”。

这就是所谓的“鸭子哲学”——一个东西,只要它看着像鸭子,叫起来也是鸭子,拿来当鸭子不会出乱子,那它就是鸭子。

————————————————————————————————————
再回到int &j=i这个声明上。

从学术上说,很显然标识符i、j,和它们代表的变量显然是不一样的,也和内存地址的某个位置没多大关系。

即: 变量i是一个抽象实体,i和j是一个关联到它的名字,而具体的某个内存地址/寄存器则是这个抽象实体在某个时刻的具体表现。

于是,编译器只要维护好抽象的变量i和标识符i、j以及实际存储它的寄存器/内存单元之间的关系,让用户可以自由使用i、j以及int *p=&i来访问它即可。

换言之,变量是个抽象概念,它可能碰巧被放在内存里,得到一个地址0x123456,也可能在某段时间内被放到cpu寄存器里,而且只要你不用地址访问它(或切换了执行现场),它就会一直仅仅存在于寄存器中。


对于语言使用者来说,他可以认为变量就等于某个内存单元,而且标识符i就等于变量i;而当考虑到编译器实现时,标识符i和变量i就必须严格区分——而这只需要从语言使用者的层次稍微推广即可,并不会颠覆已有知识。


————————————————————————————————

这里面的关键是:在使用这些概念时,必须首先指明它的内涵和外延,定义好它的使用场景。


如: 对语言使用者,有:
1、标识符i就是变量i
2、变量i就是内存单元0x123456
3、内存地址0x123456是变量i所在内存单元的索引

关键点就在于,在一本书/一篇文章中,只应使用其中一个定义,一个说法,并且这个定义、这个说法必须“自洽”,否则就会让读者糊涂。


而这种对于特定场合特定概念内涵外延的敏感而又准确的把握,显然只能在大量严谨经典的阅读中慢慢培养出来。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
187 [报告]
发表于 2010-04-14 16:33 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
188 [报告]
发表于 2010-04-14 16:53 |只看该作者
本帖最后由 shan_ghost 于 2010-04-14 16:58 编辑

事实上,考虑“可重定位”这个需求,变量就不允许等同于某个特定内存单元。

所以,变量名必然要有个到内存地址的映射,然后从这个映射再进一步找到具体的内存单元。

当然,这是从编译器角度看的。语言用户可以不知道这点(玩汇编的除外)。


所以,在语言层面上,标识符-变量之间有个映射;而在操作系统层面上,虚拟内存地址到物理内存地址又有个映射;既然段寄存器内容可以在运行时改变,那么段寄存器名字和它的实际内容之间也可以认为是有个映射……

正是这一大堆的映射,才搭建起了现代计算机系统。

先从基础的概念出发,慢慢在头脑中把这一大堆映射正确搭建起来,这才能理解现代操作系统究竟是什么样子。


相反,如果基础概念就歪歪扭扭,你凭什么把这么多复杂的映射关系搞清楚?凭什么精确找到每个映射所处的层次与位置?

我们骂那些中文书垃圾,原因就在于它们在帮你歪歪扭扭入门的同时,已经暗暗断了你今后进一步深造的路。


PS:感谢pmerofc朋友在185楼帮我强调俺的核心观点

论坛徽章:
0
189 [报告]
发表于 2010-04-14 17:03 |只看该作者
在论坛上讨论一致有无从着力的感觉:
shan_ghost:
请你不要再举哲学的这些名词来混绕了:排中律,不矛盾律,同一律这些词你不要拿出来了,大家都知道,这不能增加你论证的强度可靠性。
我们的分歧在于:
我认为标示符(我指的不是编译过程中的symbol table,如果你认为是symbol table那我们就不用讨论了)在c语言中是一个语法规则,可以用来定义变量,函数名等等。
你的观点在于:
不需要关心变量,函数名等,只关心转换后的标示符即可。

我觉得你混淆了标示符和编译处理中的符号表的概念。

具体就是这个例子:我们限定在c中
int a;
int *j = &a;
这里有两个变量。

论坛徽章:
0
190 [报告]
发表于 2010-04-14 17:12 |只看该作者
呵呵:
##
如: 对语言使用者,有:
1、标识符i就是变量i
2、变量i就是内存单元0x123456
3、内存地址0x123456是变量i所在内存单元的索引
##
很多种语言,在python中这个解释肯定是错误的,所以我们请讲讨论限定到c语言中,不然就违反了逻辑学中的同一律!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP