免费注册 查看新帖 |

Chinaunix

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

[C] 浅谈一下C语言中的指针与数组的关系 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2012-12-22 23:05 |只看该作者
Ager 发表于 2012-12-22 22:47
关于这个问题,pm大虾的《品悟C》一书有谈到,各位不妨参考一下。。。

此外,我想再讲一些。。。


这么说的话,我明白您意思了。
学习了

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
32 [报告]
发表于 2012-12-22 23:41 |只看该作者
简单地说...

int a[10];                    // --- (1)

a[5] = 12;                   // --- (2)

(1)和(2) 中都有 "[]", 但它们绝不等同:

(1) 中的 "[]" , 其作用是使标识符 a 类型确定, 该类型确定无疑由编译器负责, 具体地说, 在[编译器的]扫描器将字符流处理为 token 之后, 词法分析器记录并 (根据语言形式规则) 确定其类型.

(2) 中的 "[]" 则是一个"按下标访问"或者"按索引解引用"的运算符. 该运算符由编译器的语法分析器解析为 AST [ Abstract Syntax Tree ] 的一部分, 并由语义分析器确定其静态语义是否合法, 而后由代码生成器生成平台无关的中间代码, 而中间代码指定的是一序列执行动作, 这一系列执行动作可以看成是 (根据语言形式规则) 所确定的执行语义.

即, (1)中 "[]" 用于确定类型.
     (2)中 "[]" 用于指定执行语义.

所以, 它们之所以都是 "[]", 只不过是, 程式语言在 "类型确定" 和 "语义指定" 上的 -- 形式规则的 -- 巧合.


指针, 是一样的.
int *p;  // 这里的 "*"  用于类型确定, 或者说, 由语言 形式规则 所约定的符号.
*p = 3; // 这里的 "*" 用于指定执行语义.
这两个 "*" 绝不等同. 之所以都是 "*" -- 这只不过是语言在规定 类型确定和执行语义确定 时的 形式规则 的 巧合.

==============================

推而广之;
所谓语言: 规定形式规则 -- 赋予形式语义 -- 分类形式语义("确定类型", "指定执行语义" -- 它们都是"形式规则下的形式语义") -- 实现形式语义 -- 而实现 --》编译器 / 解释器 / 执行环境.

==============================

那么,
(1) 和 (2) 的不同, 即形式语义的不同.

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
33 [报告]
发表于 2012-12-22 23:50 |只看该作者
captivated 发表于 2012-12-22 23:41
所以, 它们之所以都是 "[]", 只不过是, 程式语言在 "类型确定" 和 "语义指定" 上的 -- 形式规则的 -- 巧合.


所言极是,真义莫若此矣。

顶captivated大虾{:3_193:}

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
34 [报告]
发表于 2012-12-23 00:09 |只看该作者

另外:

补充一下, 关于, 通过汇编学习C语言 --

通过汇编学习C语言, 能通过汇编代码理解C语言的  执行环境.
不否认理解执行环境的重要性; 相反, 鉴于目前多数计算机操作系统由C语言写就, 因此理解C语言的执行环境往往是理解 计算机系统 的一个极其重要的途径.

如在arm裸板上构建简单的"操作系统":
一开始需要通过汇编码设置一系列硬件初始化, 而后该"操作系统"的复杂性开始初步显现, 并开始迫切地需求C语言的使用, 所以第二个重要任务就是建立C语言的执行环境 -- 特简单 -- 就是设定栈起始点.
了解C语言最基本的执行环境是在编写底层程序时非常重要的一点.

然而 -- C语言仍是语言. 它不是汇编码, 也不是某个执行环境. 因此, 一旦回归语言本身, 则如下问题被提出:
形式是什么?
形式规则是什么?
形式语义是什么?
数据如何抽象?
执行流如何规划?
...

进而,
如何实现它们?
语言本身的限制?
计算机能够做到的事情的限制?

很显然, C语言不是搞定汇编就没事儿的东西

论坛徽章:
0
35 [报告]
发表于 2012-12-23 00:57 |只看该作者
本帖最后由 sqfasd 于 2012-12-23 01:02 编辑

回复 34# captivated

[]在两种场合下意义不一样是肯定的,因为本来就是两种场合或者说是两种语义嘛,一个是类型声明的一部分,一个是下标运算表达式的一部分
但这绝对不是巧合,据我所指,这是c语言的设计者故意而为之的,我前面提到,据说这是一种设计哲学
为什么不设计成
  1. int [] a;
复制代码
或者
  1. int <> a;
复制代码
又或者
  1. int_array a; //虽然这种显然不合理
复制代码
之所以设计成现在的形式,就是为了达到他们希望的效果。

我是个实用主义者,但我也能理解楼主的意思,研究语言本身的乐趣,虽然我不认同这有多大的意义= =,至少对大多数人来说

形式是什么?
形式规则是什么?
形式语义是什么?

这毫无意义,除非你以此为乐趣,否则没有实际的用途,因为这些都是中间产物

补充一句,对于编译器的开发者,和对发明语言的人,还是有意义的= =




   

论坛徽章:
0
36 [报告]
发表于 2012-12-23 01:26 来自手机 |只看该作者
至于
"
数据如何抽象
执行流如何规划
"
这是应用的能力,抽象你的业务模型的能力
好比,就算你研究透了函数指针,你还是不知道如何去实现一个面向对象的虚拟文件系统

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
37 [报告]
发表于 2012-12-23 02:15 |只看该作者
回复 36# sqfasd


    嗯, 那确实是语言设计者有意为之的事情.
    说是 "巧合" 是强调它们的不同.

    int[10] interger_ary; // 这正是 Java 声明数组的语法.

    可见: Java这种语言更加地强调了类型和对象的分离. 这种语法形式规则, 从某种程度上来说也使得类型分析变得更简单一些(对象类型可以通过自右而左分析确定).

    至于说数据抽象和执行流规划, 在语言层面上来说, 也不是业务逻辑的范畴, 它和语言设计本身相关.

    比如, 汇编语言某种程度上可以看成是无类型的. 这种无类型导致了, 任意的数据结构设计, 都由程序员自己care, 它不太有"类型限定操作"的概念 -- 比如, 在C语言中, 对double类型的对象进行 按位或/与 运算是不合法的, 因此, C语言中有"类型限定操作"这一想法的体现; 汇编中则被进一步弱化了.
    -- 类型正好是属于语言中数据抽象的范畴. 因此语言中的类型系统从某种程度上体现了 -- 如何抽象数据对象这一议题的重要内容.

    而执行流规划, 也仍是语言设计相关. 有的语言是"并行"的 -- erlang. 有的语言有corutine. -- C语言本身没有"并行"概念; C语言没有 corutine. 这和语言本身是否支持某些特性相关, 因此, 我所指的 "执行流规划" 是指语言设计时需要care的事情.

    进一步说, 有的语言有和C系语言大相庭径的语法形式规则; 它们更有和C系语言大相径庭的形式语义规则.

    至于说实用主义与否, 一般情况下我是实用主义者, 偶尔无聊了我是扯淡主义者, 因此权当扯淡罢, 呵呵.

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
38 [报告]
发表于 2012-12-23 02:24 |只看该作者
回复 36# sqfasd


    虚拟文件系统的基本数据结构就是 trie树 的变形和抽象. 我不用写一个实际的文件系统, 不过这种数据结构我玩儿过很久了. 实际可工作的文件系统当然比我写的东西复杂多了, 可我那玩意虽然简单也能用. 至于面向对象什么的, I don't care, 我就用C撸的, 不管是flash, 还是hard disk, 要是有人写个驱动并不嫌弃那数据结构简单, 将就用的话, 它也能大概表现得像个VFS的样{:3_185:}

论坛徽章:
0
39 [报告]
发表于 2012-12-23 11:42 |只看该作者
本帖最后由 sqfasd 于 2012-12-23 11:44 编辑

回复 38# captivated

我的意思是你一旦具备了设计这个系统的能力,表示你深刻理解了你的业务模型,语言本身就不是那么重要了,只要理解了函数指针,就能设计出一个可扩展的系统
当然数据结构的基本知识还是要具备的,本来应该用树来实现,你用数组也可以实现,但那毕竟是蹩脚的实现
除了数据结构的选择,还有对接口的抽象,比如不同的文件系统都有类似的open,read,write,seek等等,这个能力就跟语言没关系了,依赖于你对文件系统的了解。

论坛徽章:
0
40 [报告]
发表于 2012-12-23 13:07 |只看该作者
看得出来楼主进行了很多思考,不过还没有抓住要义。当我们要阐述数组与指针的联系(区别)时,首先要谈的是数组是什么、指针是什么,也就是应当先揭示两者的本质,在此基础上才能谈论他们之间的联系与区别。表面的语法形式可以作为一个辅助的说明,但不能作为主要的根据,这样做缺乏说服力。

关于declaretor应该如何翻译,有的时候它应该翻译为声明符,例如仅存在一个标识符这种单个词汇的情况;但有的时候应该翻译为声明器,例如pointer、array及function等这种情况,因为他们的declaretor不是一个词,而是一个语法结构,这时候称为声明器比声明符更适合。

偶还看见楼上有人说应该从汇编的角度去学习C/C++,这是在很多人身上都存在的误解。他们大多没有认识到抽象与实现之间的关系,抽象与实现之间仅具有观察者角度上的结果等效性,不具有语义等效性和过程等效性。从汇编的角度可以观察C/C++源码是如何实现的,而且也可以通过对实现过程的学习提高对执行环境的认识水平,但绝不能拿来理解C语言。像哪些“指针就是地址”、“引用就是指针”诸如此类的东西都是这种误解的结果。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP