无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
楼主: 不点
打印 上一主题 下一主题

编程语言的探究

    [复制链接]
31#
 楼主| 发表于 2017-8-20 12:44:58 | 只看该作者
谢谢前面各位高人的支持、捧场。

今天,来点“逆向思维”,用 Ch 用户手册中的例子,来检验 ROOT 的执行结果。(注意 Ch 闭源,ROOT 开源——两者不是一家的哟!)

Ch 的用户手册是 pdf 格式:

https://www.softintegration.com/download/software/release/docs/cn/chide.pdf

以下就是操作过程:

  1. firefly@firefly:~$ root    开始进入 root 环境
  2.    ------------------------------------------------------------
  3.   | Welcome to ROOT 6.10/04                http://root.cern.ch |
  4.   |                               (c) 1995-2017, The ROOT Team |
  5.   | Built for linuxarm64                                       |
  6.   | From tag v6-10-04, 28 July 2017                            |
  7.   | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |
  8.    ------------------------------------------------------------

  9. root [0] 1+3*2          在提示符下敲入算术表达式,会立即显示结果。
  10. (int) 7
  11. root [1] int i              定义变量,也会显示变量的初始值(默认值)。
  12. (int) 0
  13. root [2] sizeof(int)                显示 int 的宽度是 4 字节。
  14. (unsigned long) 4
  15. root [3] i=30              赋值,也显示结果。
  16. (int) 30
  17. root [4] printf("%x", i)        打印 i 的十六进制值,正确
  18. 1e(int) 2
  19. root [5] printf("%b", i)        企图打印 i 的二进制值,ROOT 不支持 %b 指示符。Ch 支持 %b 指示符。
  20. ROOT_prompt_5:1:10: warning: invalid conversion specifier 'b' [-Wformat-invalid-specifier]
  21. printf("%b", i)
  22.         ~^
  23. %b(int) 2
  24. root [6] i = 0b11110             用二进制格式给 i 赋值,成功,说明二进制常量是支持的。
  25. (int) 30
  26. root [7] i = 0x1E                     用十六进制常量,也成功。
  27. (int) 30
  28. root [8] i=-2                            试试负数?当然不会有问题。
  29. (int) -2
  30. root [9] float f = 10              定义浮点数,成功。
  31. (float) 10.00000f
  32. root [10] 2*f                            浮点数计算,也没问题。
  33. (float) 20.00000f
  34. root [11] double d = 10        定义双精度变量
  35. (double) 10.000000
  36. root [12] d
  37. (double) 10.000000                    都正常
  38. root [13] int i=10, *p             重新定义 i 变量,不行;同时,由于出错了,因此指针 p 的定义也无效。
  39. ROOT_prompt_13:1:5: error: redefinition of 'i'
  40. int i=10, *p
  41.     ^
  42. ROOT_prompt_1:1:5: note: previous definition is here
  43. int i
  44.     ^
  45. root [14] int *p                      因此指针 p 需要重新定义,这次成功了。p 的初值是“空指针”。
  46. (int *) nullptr
  47. root [15] &i                             显示变量 i 的地址值。
  48. (int *) 0x7fb621c020
  49. root [16] p  = &i                     把 i 的地址赋给 p,成功。
  50. (int *) 0x7fb621c020
  51. root [17] *p                             显示 p 所指向的值,即 i 的值,正确
  52. (int) -2
  53. root [18] *p = 20                    让 p 所指向的值等于 20,成功
  54. (int) 20
  55. root [19] i                                 此时 i 的值也是 20 了,没问题。
  56. (int) 20
  57. root [20] int a[5] = {10,20,30,40,50}, *p        此语句重新定义了 p,失败。
  58. ROOT_prompt_20:1:31: error: redefinition of 'p'
  59. int a[5] = {10,20,30,40,50}, *p
  60.                               ^
  61. ROOT_prompt_14:1:6: note: previous definition is here
  62. int *p
  63.      ^
  64. root [21] int a[5] = {10,20,30,40,50}    失败后,需要此语句来定义数组 a。成功。
  65. (int [5]) { 10, 20, 30, 40, 50 }
  66. root [22] a                                                      这句显示 a 数组的内容,成功。
  67. (int [5]) { 10, 20, 30, 40, 50 }
  68. root [23] &a                                                   这句显示 a 的地址,也没问题。
  69. (int (*)[5]) 0x7fb621c038
  70. root [24] &a[0]                                              这句显示 a[0] 的地址,结果与 a 的地址相同,是正确的。
  71. (int *) 0x7fb621c038
  72. root [25] a[1]                                                 显示 a[1] 的值,正确。
  73. (int) 20
  74. root [26] *(a+1)                                             换一种方式来显示 a[1] 的值。
  75. (int) 20
  76. root [27] p = a+1
  77. (int *) 0x7fb621c03c
  78. root [28] *p                                                     再换一种方式。
  79. (int) 20
  80. root [29] p[0]                                                  再换一种,都正确。
  81. (int) 20
  82. root [30] a[-1]                                                 试试数组下标越界,有警告,但仍然显示结果(=127)。
  83. ROOT_prompt_30:1:1: warning: array index -1 is before the beginning of the array [-Warray-bounds]
  84. a[-1]
  85. ^ ~~
  86. ROOT_prompt_21:1:1: note: array 'a' declared here
  87. int a[5] = {10,20,30,40,50}
  88. ^
  89. (int) 127
  90. root [31] a[5]                                                   试试数组下标越界,有警告,但仍然显示结果(=0)。
  91. ROOT_prompt_31:1:1: warning: array index 5 is past the end of the array (which contains 5 elements)
  92.       [-Warray-bounds]
  93. a[5]
  94. ^ ~
  95. ROOT_prompt_21:1:1: note: array 'a' declared here
  96. int a[5] = {10,20,30,40,50}
  97. ^
  98. (int) 0
  99. root [32] char s[5]                                         定义字符数组。
  100. (char [5]) "\0\0\0"
  101. root [33] strcpy(s,"abc")                            成功写入字符串。
  102. (char *) "abc"
  103. root [34] s
  104. (char [5]) "abc"
  105. root [35] strcpy(s, "ABCDE")                    试试写入越界字符串——竟然没有警告,不安全!
  106. (char *) "ABCDE"
  107. root [36] s
  108. (char [5]) "ABCDE"
  109. root [37] struct tag {int i; double d;} s                  重新定义了 s,失败。
  110. ROOT_prompt_37:1:31: error: redefinition of 's' with a different type: 'struct tag' vs 'char [5]'
  111. struct tag {int i; double d;} s
  112.                               ^
  113. ROOT_prompt_32:1:6: note: previous definition is here
  114. char s[5]
  115.      ^
  116. root [38] struct tag {int i; double d;} ss                 换成 ss,成功。
  117. (struct tag &) @0x7fb621c058
  118. root [39] ss.i = 20                                                            显示结构成员的值,没问题。
  119. (int) 20
  120. root [40] ss
  121. (struct tag &) @0x7fb621c058
  122. root [41] ss.i
  123. (int) 20
  124. root [42] ss.d
  125. (double) 0.000000
  126. root [43] sizeof(ss)                                                       显示结构的宽度,占用 16 字节。
  127. (unsigned long) 16
  128. root [44] srand(time(NULL))                                    设置随机数种子,成功。
  129. root [45] rand()                                                               产生随机数,成功。
  130. (int) 282375281
  131. root [46] rand()                                                               再产生一个,果然是另一个不同的数。
  132. (int) 837167582
  133. root [47] double add(double a, double b) {double c; c=a+b+sin(1.5); return c;}    定义函数,成功
  134. root [48] double c
  135. (double) 0.000000
  136. root [49] c = add(10.0,20)                                         验证计算结果,是对的。
  137. (double) 30.997495
  138. root [50] cin >> i                                                           要求从键盘输入数值给 i 变量。
  139. 10                                                                                        这个 10 是敲入的,成功赋值给变量 i 了。
  140. (std::basic_istream<char, std::char_traits<char> >::__istream_type &) @0x7fb61f4e30
  141. root [51] cout << i                                                        显示 i 的值,正确。
  142. 10(std::basic_ostream<char, std::char_traits<char> >::__ostream_type &) @0x7fb61f4ac8
  143. root [52] class tagc {private: int m_i; public: void set(int); int get(int &);}        定义一个类
  144. root [53] void tagc::set(int i) {m_i = 2*i;}                               定义成员函数 set。
  145. root [54] int tagc::get(int &i) {i++; return m_i;}                   定义成员函数 get。
  146. root [55] tagc c                                                                          重新定义变量 c,失败
  147. ROOT_prompt_55:1:6: error: redefinition of 'c' with a different type: 'tagc' vs 'double'
  148. tagc c
  149.      ^
  150. ROOT_prompt_48:1:8: note: previous definition is here
  151. double c
  152.        ^
  153. root [56] tagc cc                                                     改成 cc,成功。
  154. (tagc &) @0x7fb621c070
  155. root [57] cc.set(20)                                               调用 cc 的成员函数 set。
  156. root [58] cc.get(i)                                                  调用 cc 的成员函数 get。结果正确。
  157. (int) 40
  158. root [59] i                                                                  显示 i 的值。正确。
  159. (int) 11
  160. root [60] sizeof(tagc)                                          类变量本身占用 4 字节的宽度。
  161. (unsigned long) 4
  162. root [61] .! pwd                                   ROOT 不具有 shell 的功能,只能用这种方式调用 sh 来间接使用 shell 命令。
  163. /home/firefly
  164. root [62] .! if [ 1 = 0 ]; then echo bad; else echo good; fi                 验证 shell 的条件语句能够正确执行。
  165. good
  166. root [63] .! if [ 1 = 1 ]; then echo good; else echo bad; fi                 验证 shell 的条件语句能够正确执行。
  167. good
  168. root [64] .q                                                       测试完毕,退出 ROOT 环境,回到 shell 提示符。
  169. firefly@firefly:~$
复制代码

回复

使用道具 举报

32#
 楼主| 发表于 2017-8-24 00:44:26 | 只看该作者
今天学习一下 Ch 语言对于 Shell 里面 here document 的处理思路。在 Ch 语言的教程里面,有这样的一段话:

The following shell commands in Bourne Shell sh

  1.     #!/bin/sh
  2.     command argument << EOF
  3.       input from the console command line
  4.       abcd
  5.     EOF
复制代码

can be handled in Ch as follows:

  1.     #!/bin/ch
  2.     #include <stdio.h>
  3.     FILE *fp;
  4.     string_t command_args="input from the console command line\nabcd";
  5.     fp = popen("command", "w");
  6.     fwrite(command_args, strlen(command_args), sizeof(char), fp);
  7.     pclose(fp);
复制代码

起初,我觉得 Ch 的处理方式太复杂,难以接受。但后来,我觉得 Shell 里面的 here document,有点“添乱”的感觉,就是说,值得推敲,并不一定是个很好的设计。

首先,here document 只能处理文本,不能处理二进制数据。其次,here document 结尾的回车符,要不要呢?假如不想要,直接在 abcd 后面(同一行)跟着 EOF,这是不行的。所以这个回车符必须有,因而用户无法达到“不要结尾的回车符”的目的。第三,如果文本本身正好有一行是 EOF,那就提前结束了——如果这个程序代码是在脚本中,那么后续的多余文本行,都被错误地识别为 shell 命令,那有可能带来某些隐患。

总结一下,here document 看似方便快捷,其实陷阱很多,并不是一个完美的设计。

经过上述思考以后,我觉得 Ch 的处理方式也是可以接受的了。我在 Cling 中成功验证了 Ch 的上述代码(的思路),只增加了一行 #include <string.h> 的代码,并稍微改动了其他几处代码:


  1.     #include <string.h>
  2.     #include <stdio.h>
  3.     FILE *fp;
  4.     char command_args[]="input from the console command line\nabcd\n";
  5.     fp = popen("cat", "w");
  6.     fwrite(command_args, strlen(command_args), sizeof(char), fp);
  7.     pclose(fp);
复制代码

执行的效果等同于 shell 中的如下代码:

  1.     #!/bin/sh
  2.     cat << EOF
  3.       input from the console command line
  4.       abcd
  5.     EOF
复制代码


今天学到 Ch 的一些很有启发性的思想方法,比较满意。


回复

使用道具 举报

33#
 楼主| 发表于 2017-8-29 11:24:39 | 只看该作者
这个主题是讨论编程语言的。汇编语言(等价的机器指令的设计),也属于编程语言。

今天就记录一下最近在 grub4dos 最新改动的代码中所暴露出来的 “CPU 指令设计” 方面的问题。

  1.          subl        %es:(%di), %eax
  2.          sbbl        %es:4(%di), %edx        /* EDX:EAX=new length */
  3.          jb        5f                        /* start_address is below the base */
  4. +        ja        7f
  5. +        /* now EDX=0 */
  6. +        testl        %eax, %eax                /* EAX also be zero? ZF holds it! */
  7. +        jne 7f
  8. +        /* Change memory address type from 1 (usable) to 2 (reserved). Note
  9. +         * that original value is long integer of 1 (all higher 3 bytes = 0).
  10. +         * So only the lowest byte needs to be incremented. */
  11. +        incb        %es:16(%di)                /* memory address type */
  12. +        jmp        5f
  13. +7:
  14.          subl        %es:8(%di), %eax
  15.          sbbl        %es:12(%di), %edx        /* EDX:EAX=difference */
  16.          jnb        5f                        /* new length is too big */
复制代码

在 32 位 CPU 中,要处理 64 位的整数,就要把 64 位整数切割成两个 32 位的整数来处理。比如说上述的 64 位减法的处理:

SUB   ..., EAX
SBB   ..., EDX

第一条指令,处理低 32 位部分,SUB 指令处理的结果,会在 Flags 状态标志中有所反映。此处比较重要的是是否有借位(CF),以及结果是否为 0(ZF)。

第二条指令,处理高 32 位部分。SBB 指令能够利用上一条指令的 CF 标志,来实施本次的减法。计算的结果,当然是正确的了。

而这里暴露出来的问题,却在于有关 ZF 设置的一个细节。目前 ZF 的设置,完全是看运算结果,而这是 “不方便” 的。我们看第二条 SBB 指令,假如它的运算结果是 0,于是,ZF 也就为 True (=1)了。而这个 ZF=1 的判断,对于程序员想要了解的整个 64 位整数结果是否为 0,是 “不舒服” 的,因为它只告诉了高 32 位为 0,还得再花费两条指令判断低 32 位是否为 0 才行(浪费指令代码的空间,也浪费执行时间)。

假如 SBB 指令能改造成利用前一条指令的 ZF 结果,那就 “顺畅” 了。具体改造思路如下:

当 ZF=0 (即前面的指令没有产生 0 的结果)时,本次 SBB 依旧采用 ZF=0(即,不更新 ZF 为本次执行的结果)。(理解:只要低位部分不为 0,整个 64 位整数肯定也就不为 0 了)

当 ZF=1 (即前面的指令运算结果已经是 0)时,本次 SBB 更新 ZF(即,根据本次运算结果,设置 ZF)。(理解:低位已经是 0,那么高位是否为 0 就表明整个 64 为整数是否为 0 了)。

如此一来,SUB ... ; SBB ...; 这两条指令执行以后,ZF 的值就能代表 64 位值是否为 0 了,无需再费劲去重复判断低 32 位的情况了。

同理,“是否大于”、“是否小于” 的问题,也可以进行类似的改造。

128 位,256 位,…… 直至 “无限大” 整数,都可以进行类似的处理。rep 前缀可以重复进行字符串的处理,进一步也可以设计,让 rep 前缀应用于 “重复处理无限大的整数的算术运算”。

回复

使用道具 举报

34#
 楼主| 发表于 2017-9-3 09:48:08 | 只看该作者
本帖最后由 不点 于 2017-9-3 09:51 编辑

今天学了这个:

Cling – The New Interactive Interpreter for ROOT 6
http://inspirehep.net/record/1214956/files/jpconf12_396_052071.pdf

有很多背景知识介绍,包括疑难问题的处理,很有深度。留个脚印,以便下次还能找到。
回复

使用道具 举报

35#
发表于 2017-9-6 11:00:43 | 只看该作者
不知道不点大大有没有关注过go语言?我觉得算是最实用最好用的了,编译型的,
官方称是更好的C,实际上也继承了C,也确实可以无缝对接C程序,golang代码里就可以直接嵌进C代码。
golang自带map,slice,支持并行,gc,官方的标准库/非标准库涵盖了许多常用场景,桌面、网络、后台程序写起来都非常方便,部署也非常方便。
在方便性上比C好太多了,接近动态语言python,而在性能和部署方面又远强于python等.

点评

感谢指引。我找到了这里:https://golang.org/ Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. 我会学习一下的。  详情 回复 发表于 2017-9-6 11:08
回复

使用道具 举报

36#
 楼主| 发表于 2017-9-6 11:08:38 | 只看该作者
本帖最后由 不点 于 2017-9-6 11:39 编辑
2011grassll 发表于 2017-9-6 11:00
不知道不点大大有没有关注过go语言?我觉得算是最实用最好用的了,编译型的,
官方称是更好的C,实际上也 ...


感谢指引。我找到了这里:https://golang.org/

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

我会学习一下的。




从这里 https://golang.org/doc/faq 快速了解了一下,但很遗憾,go 没有吸引住我。可能我目前的水平比较低,还不足以让 go 来吸引住我吧。也许以后会有缘分,说不定。



回复

使用道具 举报

37#
发表于 2017-9-8 15:11:39 | 只看该作者
怎么没人提起pascal语言,这是一种国际计算机编程奥赛里面用的一种语言,结构严谨。在数学运算及围棋等方面比较强
回复

使用道具 举报

38#
 楼主| 发表于 2017-9-8 23:10:45 | 只看该作者
发现 cling 也支持 cout,记录一下,如下:

  1. [cling]$ #include <iostream>
  2. [cling]$ using namespace std;
  3. [cling]$ cout << 0 << endl
  4. 0
  5. (std::basic_ostream<char, std::char_traits<char> >::__ostream_type &) @0x7f7cd25ac8
  6. [cling]$
复制代码
回复

使用道具 举报

39#
发表于 2017-9-10 13:06:06 | 只看该作者
不点老大谈到cpu支持的指令设计问题。屮觉得这可能氏个硬件实现复杂度的问题。
软件和硬件在某种程度上有一定互代性。
比如乘法指令的实现,可以用硬件实现乘法,也可以只用加法噐,然后用软件完成乘法工作。

浮点运算也氏如此,早期的8086好像就没有浮点处理的协处理噐,浮点运算必须用整数模拟运算。
似乎arm体系的cpu很多都氏没有浮点计算硬件的。这符合arm的cpu设计时常用指令低功耗的需求。

大师说的判64位归零问题,屮想有能力设计和制造cpu的公司那几个大公司的硬件工程师,不可能不知道
如果具有相应的判零直接指令可以让软件编程时更方便,但权衡了硬件实现复杂度和经济性后有意不实现的。

此外屮觉得go语言好像和c++语言的设计目标氏一致的?难道它的目标就氏取代语言特性太复杂的c++?


点评

确实,go语言的设计者就是因为不满意c++编译太慢,特性太多,不够简洁,团队开发大型软件很烦,才有了go。不谈高深的语言设计,我也不懂,光是其简洁的语法,我觉得写起来就很舒服  详情 回复 发表于 2017-9-10 20:28
回复

使用道具 举报

40#
发表于 2017-9-10 20:28:18 | 只看该作者
本帖最后由 2011grassll 于 2017-9-10 20:38 编辑
gnuxwy 发表于 2017-9-10 13:06
不点老大谈到cpu支持的指令设计问题。屮觉得这可能氏个硬件实现复杂度的问题。
软件和硬件在某种程度上有 ...


确实,go语言的设计者就是因为不满意c++不够简洁,特性太多,编译太慢,团队开发大型软件很烦,才有了go。不谈高深的语言设计,我也不懂,光是其简洁的语法,我觉得写起来就很舒服
回复

使用道具 举报

41#
发表于 2017-9-13 00:06:03 | 只看该作者
语法简洁只氏评判语言的一个方面。若论简洁,脚本语言更简洁,一行脚本超过万行c程序。
程序设计语言很多,各种语言都有自已的适用领域。

有生命力的语言或开发工具,肯定要有某种重量级的应用程序采用它编程,才有说服力。
比如说linux内核以及其它操作系统内核,用c语言写成;GCC编译噐集,用cjj写成;
gtk有gnome桌面生态,qt有kde桌面生态;

这些都氏重量级的应用程序或环境,能开发它们的工具、语言、类库当然值得信赖和学习。
go语言怎么也得等它有重量级的应用使用它做开发时,程序员才能更有选择它的理由。


回复

使用道具 举报

42#
 楼主| 发表于 2017-9-13 06:57:58 | 只看该作者
有各位高手捧场交流,真是荣幸。看了各位高论,也谈点自己的浅见。

C、C++ 的语法形式,太过于复杂。语法分析器的负担很重。这肯定算是缺点。Basic 语言最简单。我最早学习的那种 Basic,没有循环语句,只有 if 语句。那时候,大量使用 goto 语句。Basic 语言的赋值语句需要有 let 关键字(后来,let 可以省略,但我觉得糟糕了,因为有了 let 会更清晰一些)。后来的 basic 有了各种控制结构。子程序调用,需要 call 命令。子程序声明,需要 SUB 关键字。有了这些规范,程序才显得井井有序。

C、C++ 的语法太自由了,这给语法分析器带来了巨大负担。从 C、C++ 用户的角度来看,当然很自由、很舒服。所以,优点可能也是缺点,缺点也可能是优点。

目前世上有多少种编程语言?是几千?还是几万?可能没人知道准确的数目。但是,有些东西却是可以说清楚的,那就是“历史”。历史上首先有机器语言,然后有更人性化的汇编助记符(assembly),好像紧接着就是 C 语言了吧?我不知道是谁设计了 C 语言,但我很佩服此人,我觉得他很伟大。C 语言就像“世界语”一样,到处通行无阻,任何平台都支持 C 语言。别的语言都可以没有,只要有汇编语言和 C 语言,世界照样运转。哦,不要误会,我的意思是说,汇编语言和 C 语言是最基本的语言。我没否认其他语言的地位和作用。各种语言都有其“用武之地”。

回复

使用道具 举报

43#
发表于 2017-9-13 09:10:10 | 只看该作者
本帖最后由 2011grassll 于 2017-9-13 10:40 编辑

一门语言好用,能够令人满意的完成任务,才是程序员选择它的理由,而重量级应用也就会因此不断的产生。

go语言标准库中的网络部份很令人称道,事实上已经是各种云平台的重要选择,国内大家熟知的BAT京东等都有用到,创业公司用的就更多。
另外有个docker,在容器领域中独占鳌头,算得上是一个重量级应用。
而这些只是应用的几个方面,一门语言能做的还有很多。

c,c++在接近硬件的层次是无可匹敌的(虽然我觉得写起来有点不那么愉快),go更偏向应用层。

@gnuxwy:bash类脚本在某些方面和操作系统交互很方便,而用bash本身的语法写逻辑是很烦的。

@不点大大:ken thompson也在go语言的创始团队中

点评

谢谢指点。原来是 Ken Thompson 开发了 Unix 和 C 语言。好厉害。 很遗憾,我目前没有对 go 语言感兴趣。  详情 回复 发表于 2017-9-13 13:29
回复

使用道具 举报

44#
 楼主| 发表于 2017-9-13 13:29:37 | 只看该作者
2011grassll 发表于 2017-9-13 09:10
一门语言好用,能够令人满意的完成任务,才是程序员选择它的理由,而重量级应用也就会因此不断的产生。

...

谢谢指点。原来是 Ken Thompson 开发了 Unix 和 C 语言。好厉害。

很遗憾,我目前没有对 go 语言感兴趣。
回复

使用道具 举报

45#
发表于 2017-9-13 17:46:23 | 只看该作者
本帖最后由 2011grassll 于 2017-9-13 18:55 编辑

也没啥,有需求才有缘份,如果我不是有一个场景用c太累人,用python性能不够,也不会尝试go的
回复

使用道具 举报

46#
发表于 2017-9-16 00:32:16 | 只看该作者
屮可不氏什么大神。。。一个菜的不能太菜的编程瞎玩者而已。比起不点大师和楼上的grassll坛友,可能连门都
没有进过。只氏十几年来也多少也接触过好几种语言。。。

和不点一样BASIC也是NN年前接触过,还买过一本小书叫趣味编程一百例吧,小霸王学习机玩过几天就弃了。

后来有VB,也氏玩了几天。再后来就氏pascal,为了考试,断断续续学过一年,后来玩delphi,又用过两个月。

再后来继续考C和C++,又学过年把,也玩过VS2006。。。操,到处找稳定的破解版。
嗯,听说java不错,比Cjj语法漂亮。。。天啦,eclips怎么这慢啊。。。弃之。
别人送了一本C#的书,噢,微软版的java,要不要试试呢?。。。还氏不折腾算了。。。

你瞧,屮氏接触过好几种编程语言吧。。。浅尝辄止的接触。
当然,没一个用得熟的。自已练习写的小程序,最多也不过几百、几千行代码。

后来,偶尔接触到gnux/ubuntu,原来除了windows,还有其他的操作系统可用啊!
而且系统竟然不免费配送木马、病毒、流氓、间谍,也没有一大堆垃圾打包进来!!
不要钱的正版系统还这么好用?----后来当然知道,钱氏不要的,要的氏花点心思和时间熟悉、适应新系统。

正好接触gnux时年纪大了,不怎么玩游戏了,干净的gnux系统正合屮意。
要玩命令行,bash多少要学点。写点小程序,再把C捡起来重新再学下。。。

请问不点大师和grassll坛友,glib的库很完善很强大,但氏怎么没有中文手册啊。。。屮英文水平比较烂。
屮有一本纸质的linux的C函数手册,很有用,但远没有glib的库函数那么全面实用,可一直找不到中文手册。


回复

使用道具 举报

47#
 楼主| 发表于 2017-9-16 07:58:44 | 只看该作者
楼上 gnuxwy 过谦了。光是你的经历,都有着压倒性的优势,本人差很远,不值一提。我除了业余自学 BASIC、C、汇编,没再学过别的语言,虚度光阴了。也没参加过任何种类的计算机水平考试。

Linux、开源,其最大好处是,让像我这样“下三烂”水平的人,能够“喘一口气”、“呼气点新鲜空气”、“找到自己的存在感”——别小看了这一点,我认识到,“刷存在感”是人生的一个基本需求。绝大多数人都被淹没在汪洋大海之中,不显眼,缺乏“存在性”。这些人为了证明自己活着还有意义,就要到处寻觅,寻找那些适合于证明自己“存在”的东西。普通人永远都是大多数的,因此,上述这种情况永远不会改变。也因此,“刷存在感”的需求量是很大的,这种“欲望”是消灭不掉的。这就从一个视角再次证明了,Linux、开源是消灭不掉的,就连微软都接受了这一点(尽管它很不情愿)。——以上是今天的感想。有想法就分享出来,也算是证明了自己还活着吧。
回复

使用道具 举报

48#
 楼主| 发表于 2017-9-16 13:23:24 | 只看该作者
记录一下,cling 的入口文件是这个:

src/tools/cling/tools/driver/cling.cpp

我目前对其交互式操作感兴趣,也就是如下这行代码

  1. Ui.runInteractively(Opts.NoLogo);
复制代码


而函数 runInteractively() 的定义在这个文件中:

src/tools/cling/lib/UserInterface/UserInterface.cpp

其中,关键是这一行:


  1. const int indent = m_MetaProcessor->process(Line, compRes);
复制代码


函数 process 的定义在这里:

src/tools/cling/lib/MetaProcessor/MetaProcessor.cpp

这个函数的代码不多,但比较重要,所以,抄录下来:


  1. int MetaProcessor::process(llvm::StringRef input_line,
  2.                              Interpreter::CompilationResult& compRes,
  3.                              Value* result,
  4.                              bool disableValuePrinting /* = false */) {
  5.     if (result)
  6.       *result = Value();
  7.     compRes = Interpreter::kSuccess;
  8.     int expectedIndent = m_InputValidator->getExpectedIndent();

  9.     if (expectedIndent)
  10.       compRes = Interpreter::kMoreInputExpected;

  11.     if (input_line.empty() ||
  12.         (input_line.size() == 1 && input_line.front() == '\n')) {
  13.       // just a blank line, nothing to do.
  14.       return expectedIndent;
  15.     }

  16.     //  Check for and handle meta commands.
  17.     m_MetaParser->enterNewInputLine(input_line);
  18.     MetaSema::ActionResult actionResult = MetaSema::AR_Success;
  19.     if (!m_InputValidator->inBlockComment() &&
  20.          m_MetaParser->isMetaCommand(actionResult, result)) {

  21.       if (m_MetaParser->isQuitRequested())
  22.         return -1;

  23.       if (actionResult != MetaSema::AR_Success)
  24.         compRes = Interpreter::kFailure;
  25.        // ExpectedIndent might have changed after meta command.
  26.        return m_InputValidator->getExpectedIndent();
  27.     }

  28.     // Check if the current statement is now complete. If not, return to
  29.     // prompt for more.
  30.     if (m_InputValidator->validate(input_line) == InputValidator::kIncomplete) {
  31.       compRes = Interpreter::kMoreInputExpected;
  32.       return m_InputValidator->getExpectedIndent();
  33.     }

  34.     //  We have a complete statement, compile and execute it.
  35.     std::string input;
  36.     m_InputValidator->reset(&input);
  37.     // if (m_Options.RawInput)
  38.     //   compResLocal = m_Interp.declare(input);
  39.     // else
  40.     compRes = m_Interp.process(input, result, /*Transaction*/ nullptr,
  41.                                disableValuePrinting);

  42.     return 0;
  43. }
复制代码


可以看到,它是逐行处理输入数据的。先处理“元命令”。仅当不是元命令时,才交给解释器去处理。

然而,一旦交给解释器,解释器就把输入数据完全当成 C 语言代码了。如果失败了,那就在解释器里面显示错误。比如说,交给一行 shell 命令,此时,解释器只能显示错误。而理想的情况是:它不急于显示错误,而是尝试调用 shell 来进行 shell 的语法分析。如果符合 shell 语法,那就按 shell 命令对待。否则,先显示 C 语言解释器的出错信息,再显示 shell 的出错信息。

回复

使用道具 举报

49#
 楼主| 发表于 2017-9-16 14:03:42 | 只看该作者
解释器的处理代码在这里:

src/tools/cling/lib/Interpreter/Interpreter.cpp

代码也不长,抄录下来:

  1.   ///\brief Maybe transform the input line to implement cint command line
  2.   /// semantics (declarations are global) and compile to produce a module.
  3.   ///
  4.   Interpreter::CompilationResult
  5.   Interpreter::process(const std::string& input, Value* V /* = 0 */,
  6.                        Transaction** T /* = 0 */,
  7.                        bool disableValuePrinting /* = false*/) {
  8.     std::string wrapReadySource = input;
  9.     size_t wrapPoint = std::string::npos;
  10.     if (!isRawInputEnabled())
  11.       wrapPoint = utils::getWrapPoint(wrapReadySource, getCI()->getLangOpts());

  12.     if (isRawInputEnabled() || wrapPoint == std::string::npos) {
  13.       CompilationOptions CO = makeDefaultCompilationOpts();
  14.       CO.DeclarationExtraction = 0;
  15.       CO.ValuePrinting = 0;
  16.       CO.ResultEvaluation = 0;
  17.       return DeclareInternal(input, CO, T);
  18.     }

  19.     CompilationOptions CO = makeDefaultCompilationOpts();
  20.     CO.DeclarationExtraction = 1;
  21.     CO.ValuePrinting = disableValuePrinting ? CompilationOptions::VPDisabled
  22.       : CompilationOptions::VPAuto;
  23.     CO.ResultEvaluation = (bool)V;
  24.     // CO.IgnorePromptDiags = 1; done by EvaluateInternal().
  25.     CO.CheckPointerValidity = 1;
  26.     if (EvaluateInternal(wrapReadySource, CO, V, T, wrapPoint)
  27.                                                      == Interpreter::kFailure) {
  28.       return Interpreter::kFailure;
  29.     }

  30.     return Interpreter::kSuccess;
  31.   }
复制代码


它主要是调用 DeclareInternal() 和 EvaluateInternal() 函数,这两个函数也在该文件中定义。函数的返回值表示“成功”或“失败”。


回复

使用道具 举报

50#
发表于 2017-9-16 18:11:08 | 只看该作者
俺一共写过三个大些功能完善的程序
1,第一个按键精灵写的
2,第二个 ahk写的
3,第三个delphi写的
回复

使用道具 举报

51#
发表于 2017-9-18 09:51:03 | 只看该作者
gnuxwy 发表于 2017-9-16 00:32
屮可不氏什么大神。。。一个菜的不能太菜的编程瞎玩者而已。比起不点大师和楼上的grassll坛友,可能连门都
...

估计是因为中国搞底层开发的并不多,所以没有去翻译吧,大部分的编程文档都只给了英文的,都是爱好者去翻译的,qt之类的官方也只有英文文档吧

另外,真正做底层开发的,估计英语也学的差不多了,或者比较了解底层知识,再加上一点翻译软件就基本能够读懂了

点评

windows的各种开发手册就不少。其实glib确实氏很好的强大全面的C库,也能跨平台使用。 主要还氏中国gnux程序员规模不够,影响力不够,所以这么好的C库,没有中文手册,确实太遗憾了。  详情 回复 发表于 2017-9-21 01:03
回复

使用道具 举报

52#
发表于 2017-9-18 12:08:44 来自手机 | 只看该作者
能不能跟不点大师学,肯求不点大带路

点评

不要跟我学。我还想跟别人学呢。我虽然也(像毛主席一样)爱人民,但我可不是那带路人。我虽然也是“为了建设新中国”,可我不能“领导我们向前进”。 说实在话,我还真幻想着有懂开发的高手凑过来,整合出一个好  详情 回复 发表于 2017-9-18 23:36
回复

使用道具 举报

53#
 楼主| 发表于 2017-9-18 23:36:52 | 只看该作者
2010eflying 发表于 2017-9-18 12:08
能不能跟不点大师学,肯求不点大带路

不要跟我学。我还想跟别人学呢。我虽然也(像毛主席一样)爱人民,但我可不是那带路人。我虽然也是“为了建设新中国”,可我不能“领导我们向前进”。

说实在话,我还真幻想着有懂开发的高手凑过来,整合出一个好用的编程语言。

目前我觉得 cling 很不错。zsh 又比 bash 强大。因此,我在考虑,最好能整合出一个新的 shell,具有 zsh 和 cling 的功能。

先不说难度有多大,只说这事有没有可能干成。——绝对有可能干成——因为闭源的 Ch shell 就正好支持 C 语言代码的解释执行。所以,开源的整合,肯定有希望成功,只是需要时间罢了。

回复

使用道具 举报

54#
 楼主| 发表于 2017-9-19 13:23:47 | 只看该作者
今天有一点认识,那就是,不用考虑某一个软件、某个东西有多少用户。用户的多少,不是判断一个东西好坏的唯一标准。有些东西,注定用户不多。比如 Linux 可能就是这样。Ch 这种语言,也没有太多用户,我个人感觉,其用户数量甚至比 Linux 用户还要少。然而,它达到的那种高度,目前是无可替代的,是一流水平。只要你喜欢的、需要的,那就是最好的。就像真理一样,你认为啥是真理,那它就是真理。

点评

编的东西能解决实际问题,再小的程序也有懒人用;就像汇编破解,无论是看书多少本,还是理论书看了多少那些即重要也不重要,只是铺垫和思路而已,关键还得兴趣+实战,偶尔用用都比几个月不练的要好很多。  发表于 2017-9-19 16:37
回复

使用道具 举报

55#
发表于 2017-9-19 16:19:45 来自手机 | 只看该作者
自要是自己用得到的就拿来用
回复

使用道具 举报

56#
发表于 2017-9-21 00:58:39 | 只看该作者
不点老大也觉得zsh好啊。。。最近看了网上些文章,也觉得zsh真心功能比bash强不少。
也许bash几十年的首选地位真的要受到zsh的挑战了。
若不点老大能把C解释执行的功能加到zsh中去,肯定能给zsh大大加分。

话说中国的计算机教育太过捧微软的臭脚了。。。
记得以前参加计算机实践课考核时,机房里所有系统全氏windows(估计也全氏盗版)。
屮说屮的C语言程序要在gcc下编译,监考的女老师睁大眼睛望着屮,
“gcc氏什么编译噐啊?”屮解释说氏gnu的编译噐,她不知gnu氏啥,好在另一个监考的男老师倒氏知道。
说明学校的机房里没有gcc编译噐,最后屮只好用自带的网络本编译程序了。

还有考数据库时,非得指定用微软的sql2000做范例数据库,结果写查询语句时,sql2000不氏与标准sql语言
完全一致的,时间又紧,结果数据库实践课不及格,下半年再补考。补考前为了装上盗版的sql2000,折腾的要
死,装了N个版本,失败了MM次。碰运气才在某台机上安装成功。真不明白,大把的开源数据库不用,非得吊
死在微软的sql2000这个不使用标准sql语句的数据库上。个人觉得,作为考核sql语句,sqlite最合适不过了。

真心希望,gnu编程环境以后在计算机教学中能成为重要组成,除了对微软不利外,各方面都有好处。





回复

使用道具 举报

57#
发表于 2017-9-21 01:03:47 | 只看该作者
2013olly 发表于 2017-9-18 09:51
估计是因为中国搞底层开发的并不多,所以没有去翻译吧,大部分的编程文档都只给了英文的,都是爱好者去翻 ...

windows的各种开发手册就不少。其实glib确实氏很好的强大全面的C库,也能跨平台使用。
主要还氏中国gnux程序员规模不够,影响力不够,所以这么好的C库,没有中文手册,确实太遗憾了。
回复

使用道具 举报

58#
 楼主| 发表于 2017-9-21 06:32:42 | 只看该作者
你的意思,我试试理解一下。你是说,中国的计算机教育,就是在给微软培养打工仔。学生毕业之后,只能以各种方式去给微软打工。

存在皆合理。为了达到上述效果,微软也是花了本钱的。我分析(其实是八卦),微软采取了两个关键举措。其一,纵容盗版,让微软系统的普及尽可能达到 100% 的程度。其二,从上游公关,控制国家或学校、企业的高层,令其乖乖听从微软指挥。想想看,中国这样的体制,能抵挡住微软的进攻吗?根本就不能。其实不只是中国不行,放眼世界,别国也照样抵挡不住微软的进攻。无论哪个国家,都有官僚体制。谁能举个反例,说某个国家完全没有官僚体制、完全能够抵挡微软的进攻?一个都没有!就连欧洲的反垄断调查机构,都可以被收买。不服不行。所以我说,存在皆合理,不用纠结,不用去追究。

中国要崛起,路还很漫长。扳指头算算,现有的几个巨头,表面上多么光彩、多么华丽,其实它们的内核、实质,却都是别人的奴才。它们是国人的主子,却是别国人的奴才。它们无一例外地——要么是微软的奴才,要么是苹果的奴才,要么是谷歌的奴才。不知道这些奴才们,将来会不会有《从奴隶到将军》的一天。依我目前的观察,很难,没什么希望。打个比方:就算皇帝死了——皇帝的位置空着——一个奴才也不敢想着去做皇帝。你更不能指望这个奴才能够秸秆起异去打败皇帝。奴相十足,这也是国人的一种存在,因此也是合理的。

另一方面,微软统治世界几十年之后,却遇到大麻烦了。从表面上看,正如前面的分析,微软还能用各种公关手段买通上层官僚,压制其他竞争对手(包括“开源”这个最大、最根本性的敌人)。而其实,这已经暴露出微软的空虚了——是不是在唱《空城计》?纯粹靠“压制”,能维持统治吗?根据历史的规律,这些压制,这些统治,迟早也是要破灭的。微软在垮台之前,肯定要唬人,唬住一个是一个。万一哪天唬不住人了,那时,就轰然倒塌了。

假如一群奴才给微软抬轿,替微软喝彩,你看到了之后,会怎么想?我真的不能揣测别人会怎么想,我只能说说我此刻会怎么想。我会这样想:幸亏那群人里面没有我。人家愿意干啥,那是人家自己的事啊。人家饿了要吃饭,没来找我要钱,我啥也不管人家,我不用替人家操心,我没有任何成本的投入,我也就没有资格去管人家的任何事。那么人家愿意给谁抬轿,抬就抬呗,没什么不可理解的。他给谁抬轿,谁就给他钱,这是公平交易。尤其是,我不能指望人家来给我抬轿啊!假如我那样去幻想的话,那我不就是傻子吗?还有一种可能性,有一部分人可能是被骗去抬轿了,人家并不给钱,或更有甚者,干脆偷偷地把他的肾割掉,卖给医院。网上经常看到被骗的人。这些被骗者,他们被骗了,是他们自己的事情,是他们的造化,是他们的智力或能力使然,你无法去拯救他们。有些人,你能去救。有些人,你不适合去救。有些人,会求你去救他。有些人,根本不想让你去救他(比如想自杀的人)。有些人,你想去救人家,可是人家根本瞧不上你!你都没资格去救人家!人家甚至看你日子过得艰苦,反过来还想救你一把呢!!!!!!诸如此类,等等等等……。大千世界,人有各相,五花八门,难以捉摸。
回复

使用道具 举报

59#
发表于 2017-9-21 14:09:01 | 只看该作者
gnuxwy 发表于 2017-9-21 01:03
windows的各种开发手册就不少。其实glib确实氏很好的强大全面的C库,也能跨平台使用。
主要还氏中国gnux ...

也就是主流的win32有中文手册吧, native api和ddk/wdk的文档我好像也没找到中文版
回复

使用道具 举报

60#
发表于 2017-9-21 20:51:21 | 只看该作者
本帖最后由 slore 于 2017-9-21 20:54 编辑
话说中国的计算机教育太过捧微软的臭脚了。。。


主要是linux系统根本不行好吧.
机房的机器能从老师机器整体控制,能共享桌面操作,linux能?有这种教学软件?
当时连带桌面的系统都没有吧.

大街上拉10个人,有1个用linux都不错了,机房全用linux?出了问题,谁给配置,重装配置网络谁给搞?
老师给你教C语言,数据库,不是来给你搞环境,懂系统管理维护的.
这方面Windows非常傻瓜化,普及,当然用Windows.
如果是学校买的正版的话,服务支持也比linux靠谱的多,交了钱的.

就像你学编程开发,你老师给你教怎么安装Windows,装机器,优化系统服务,改注册表的课么?

学习资料,比如C,结构体,算法不能在linux上用?这些知识是通用的,只不过Windows更方便操作些.
老师要给你教怎么写makefile?要学习make,link命令行?
学校教的基本数据结构,数值,字符串的各种算法,都是通用,反倒根本不给Windows打工,
Windows那么多系统API,谁给你教过?获取窗口句柄,操作控件内容,创建系统服务,更改注册表配置等等,根本没有.

access为什么还有,VF还活着.当时开源数据库不成熟,你说的sqlite数据都是明文不加密的,
商业谁用?虽然是练习学习SQL吧,起码以后会用的环境,微软有ODBC,后面JDBC也有接口,从其他的方式访问.
开源的数据库当时谁厉害?另一家oracle,商业又贵,软件大,功能强配置复杂.谁机器愿意装?

虚拟机软件当时几个人知道,VM又是商业软件,谁给全国老师交钱培训?

现在开源软件发展好了,但是国家体制的人懒,能用就凑合用,不会投入成本更新的,老师也不愿意多学,学生更不会想敲命令.
比如代码管理,SVN,GIT,当时上学不是一个个文件夹复制,打包压缩包?
有给你搭服务器管理么?这个是个好东西,但是即便10年,学校教育是不会给你教的.

咋简单,咋省事再来.相对于linux上,Windows上安装环境还是容易,基本上重装下很多都能解决.
linux不联网,各种库坑死人,有些还得自己编译source.

真心想学习的人,自然有途径和动力去找好的东西,比如开源产品.
大部分,绝大部分人不过应付一个任务而已.对于愿意学习的人没有影响,
对不愿意学习的人省事,没觉得用Windows有什么错.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-12-10 22:44

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表