免费注册 查看新帖 |

Chinaunix

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

对C语言指针的讨论:应当如何理解、使用指针?《狂人C:程序员入门必备》有奖试读 [复制链接]

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
161 [报告]
发表于 2010-12-17 00:06 |只看该作者
感谢,感谢!
    我对图也很不满意
KBTiller 发表于 2010-12-16 23:59


或者可以弄个网站做个补充说明或者勘误会,答疑解惑。

论坛徽章:
0
162 [报告]
发表于 2010-12-17 00:25 |只看该作者
或者可以弄个网站做个补充说明或者勘误会,答疑解惑。
mirnshi 发表于 2010-12-17 00:06



    这里的老大已经答应可以在CU弄了

论坛徽章:
0
163 [报告]
发表于 2010-12-17 20:25 |只看该作者
sagasw网友的阅读笔记
将在github的wiki上做持续更新,这里做个copy

https://github.com/saga/sagasw/wiki/%E7%8B%82%E4%BA%BAC



整体问题

对于C标准库的说明都说是编译器实现,这一点是不准确的,参考维基百科http://en.wikipedia.org/wiki /C_standard_library

提到一个真正是莫名其妙不知所云的C语言中国国家标准,这是个什么玩意?谭浩强主编的?

primary expression翻译成初等表达式,这个是败笔,难不成还有中等表达式和高等表达式?我建议如果再版,改做“基本表达式”,元表达式也不妥,一般来讲编程中的“元”多从“meta”这个单词产生,如metaprogramming。

page37, printf("%d\n", 1234567890123); // 0x11f71fb04cb 在little-endian机器上,大部分我们机器,如Intel、AMD,结果都应该是1912276171(0x71FB04CB),而在 powerpc的ibook g4 big-endian机器上,结果为287(0x11F)。这个结果是有章可循的。

page38, 应该说明sizeof不会对表达式求值。 sizeof(m++); // m will NOT increase

page62,"后者也是一种错误代码",感觉提法不容易理解,-> “标准未定义的代码也是应该避免的"。

预处理命令 #definede : typo

注释在编译前被替换成空白字符,这部分待查(gcc,vc)。

page63,风格习惯。命名规范问题,应该用准确的英语做标记。reminder = dividend % divisor; better than ys = bcs % CS;

常见错误,/* comment */,一般常见的IDE会有代码着色功能,如VC++会把注释标记为绿色,而大部分编辑器如vim (textmate)也可以做标记着色。


page113,“如果代码中有两个错误,那就不是两倍,而是平方”,这句话意思容易理解,但细看会很别扭,我们假设修改难度为1的话,那么两倍和平方...

page118,typo, lable -> label

论坛徽章:
0
164 [报告]
发表于 2010-12-19 07:08 |只看该作者
关于 sagasw网友的阅读笔记 中提到的国家标准
提到一个真正是莫名其妙不知所云的C语言中国国家标准,这是个什么玩意?谭浩强主编的?


这个标准是 GB/T 15272-94 (程序设计语言C)
是1994年由国家技术监督局发布的
实际上是C90的中文翻译本
主要是由金益民(好像是西安电子科技大学的)、孙玉方等几个人弄的
谭浩强是绝对搞不来这种东西的
金益民、孙玉方的C语言书我读过
里面还是有些东西的
孙玉方听说是中科院的
这个人在80年代做了不少C语言的引进和介绍工作
我个人认为孙应该算是国内C语言的先驱之一
(btw:谭的书是91年才出的)
GB/T 15272-94翻译的很粗糙
错误也不少
全然没有标准应有的那种庄严感和权威性
而且远远落后于时代
但考虑到GB/T中的T(推荐)
似乎也拿它没什么办法
权当它不存在好了
也难怪连sagasw这样的C语言资深网友都不怎么知道它

论坛徽章:
0
165 [报告]
发表于 2010-12-20 22:42 |只看该作者
本帖最后由 KBTiller 于 2010-12-20 22:48 编辑

关于本书191页
“每次运行到auto变量j所在block,会为j寻找存储空间,离开j所在代码模块,j的内存被释放掉。”的讨论

C语言中本地变量local variable的作用域与生存期
http://bbs.chinaunix.net/thread-1834663-1-1.html


附:

6.11.1  几乎一直是摆设的关键字——auto
auto这个关键字在C语言中一直是个摆设,原因是auto是局部变量的默认修饰。也就是说,如果局部变量前不加任何存储类别说明符,那么这个局部变量就是auto类别的。前面用到的所有局部变量都是auto类别的。

auto类别的局部变量的含义是在用到这个局部变量时,“自动”地为它找个存储空间,离开它的作用范围后,它所占据的空间自动地还给计算机。这里所谓的不再用到是指,这个局部变量所在的代码模块已经被执行完了。当程序再次开始执行auto类别的局部变量所在的代码模块中的代码时,会再次为这个变量寻找一个存储空间,基本上这个空间和上一次它所占据的空间是不一样的,即使一样也毫无意义,因为原来所占据的内存空间既然还给了操作系统,那么里面的内容——原来的值,可能早就面目全非了。


  1. //auto类别局部变量的特点的演示

  2. #include <stdio.h>

  3. int main(void)
  4. {

  5. int i;



  6. for(i=0;i<3;i++)

  7. {

  8. auto int j = 1 ; //这是个auto类别的局部变量,也可以写为 int
  9. j = 1 ;


  10. //每次程序执行到这里时重视为这个变量寻找一个库存出空间

  11. //每次都为这个变量赋一个初值 1

  12. printf("%d\n",j);


  13. j++;

  14. }
  15. //程序执行到这里后变量j所占据的内存就被释放了

  16. //也可以理解为j已经不存在了,因为它的存储空间可能被挪做它用

  17. system(“Pause”);

  18. return 0;
  19. }

复制代码



这段程序的运行结果是:

1
1
1
请按任意键继续. . .



这表明了每次运行到j所在的代码模块时,都为j寻找存储空间并且重新为j赋初值1。而且每次离开j所在的代码模块时,j的内存都被释放掉。

形参的性质是一样的,形参也是在被调用时才拥有自己的存储空间,在return时这个空间被释放掉。

论坛徽章:
0
166 [报告]
发表于 2010-12-20 22:51 |只看该作者
这里所谓的不再用到是指,这个局部变量所在的代码模块已经被执行完了。

其实这段文字有点问题
“这里所谓的不再用到是指”,这句的前面原来有“不再用到”这个词
但前面的文字修改了
后面的这句“这里所谓的不再用到是指”却没有修改
可能会给人一种莫名其妙的感觉
非常抱歉!

论坛徽章:
0
167 [报告]
发表于 2010-12-20 23:10 |只看该作者
这段的文字表述也有问题
我将会换种表达方法

论坛徽章:
0
168 [报告]
发表于 2010-12-21 09:55 |只看该作者
本帖最后由 KBTiller 于 2010-12-21 10:04 编辑

sagasw网友提到的++部分
5.3.2  ++”之惑
      在前面for语句的例句中,i++和i = i + 1所起到的效果是完全相同的,但实际上这两个表达式真正的含义却并不相同。由于++很容易给初学者带来困惑,所以有必要在此详细剖析一下。
1.        有几种“++”?
      一共有两种++运算符。一种++运算符是写在运算对象的后面,如前面小节代码中的i++,另一种++运算符是写在运算对象的前面,例如++i。
      写在运算对象后面的++叫后缀加运算符(Postfix increment operator) ;写在运算对象前面的叫前缀加运算符(Prefix increment operators),是个一元运算符。这两种运算符一模一样,但是它们的优先级和结合性却完全不同。前者的优先级是16(最高级别,和函数运算同级),结合性从左到右;而后者的优先级是15(和所有一元运算符相同),结合性从右到左。
      这情形和“-”既可以作为减法运算符也可以作为求负值运算符一样。在“5-3”这个表达式中,“-”是减法运算符,优先级为12;而在“-3”这个表达式中,“-”是求负值运算符,优先级为15。编译器可以通过“-”所处的上下文判断出它究竟是哪种运算。代码的编写者更应该清楚两者之间的差别。
      在这一点上,很多初学C语言的人都很容易轻率地认为两者是同一个东西。但是,从以上介绍来看,它们两者之间真的是相去甚远。
      不过,无论是后缀加还是前缀加,其运算对象都必须是左值表达式(严格地说是可修改的左值表达式)。而所谓的左值表达式,到目前为止我们只见过一种,就是单个变量名构成的初级表达式(也可以在变量名外面加上(),这种写法十分罕见,但含义一样)。
2.        两种“++”运算符的区别
      上面说的是++运算符具有两种不同的意义,那么在实际操作中,两种运算符究竟又有什么不同呢?下面以int类型变量i为例进行介绍。
      对于一个int类型变量i,++i的确切含义是求i的值,此外这个运算还有一个“副效应”(Side effects),即是在求i值之前,先将i赋值为i+1。而i++的确切含义同样是求i的值,这个运算也有一个副效应,即是求完i值之后,将i赋值为i+1。
      现在核心的问题就出现了。上文中的“求i值之前”和“求完i值之后”,这只是一个时间范围,而并不是一个确切的时间点,因此我们还是不知道到底在何时i会被赋值为i+1。总不能在程序一开始运行的时候就加1吧,要知道那时候变量可能还不存在或者还没定义呢;也总不能等程序运行结束之后再加1吧,那样的副效应还有什么意义呢?
      此时,必须借助“序点”(Sequence Point)这个概念才能把这个问题说清。所谓序点,简单地说,序点就是程序执行时一些虚拟的“节点”,这些“节点”对应着代码中一些特定的位置。在这些“节点”之前代码所要求计算机执行的所有动作(包括副效应)必须在这个“节点”处必须完成。由此可见,序点是C语言用于规定或说明运算次序的一个基本概念。

就目前为止,我们见过的序点有语句的结束标志“;”或”}”,“? (问号),“, (逗号),if语句、while语句、do-while语句及for语句中的()的“)”,for语句“()”中的“;”,此外main()函数的“{”实际上也是一个序点。

因此,不难理解,表达式“i++”的真正含义即是,在求得i值之后,下一序点之前,完成i=i+1这个副效应操作(表达式永远是用来求值的,其余的都是副效应)。而表达式“++i”的真正含义是在前一序点之后,求i值之前,完成i=i+1这个副效应操作。

同理,--运算符也有两个不同的意义,即后缀减运算符和一元前缀减运算符,除了表示在求变量值之后(之前)变量的值需要被减去1之外,其性质和对应的“++”运算符是一致的。

此外要说明的是,“++”、“--”(无论是前缀还是后缀)的运算对象可以是任何整数类型、实浮点类型或指针类型。

论坛徽章:
0
169 [报告]
发表于 2010-12-21 10:21 |只看该作者
回复 168# KBTiller


    我对这段解释的看法是,为了解释++,键盘农夫不得不在一开始就引入更为难懂的概念“左值”“右值”(我对书中这个概念几乎都是跳过),
第一点,C语言中(至少是在K&R中)我没有看到右值的提法,RValue其实是从C++跑来的。
我在今年五月份还试图写博客来解释这个问题,http://sunxiunan.com/?p=1628 除了堆砌一些专家的提法,感觉解释的很不成功。

    用汇编语言解释是很讨巧的一种方式,但是作为教科书可能没法使用,因为不可移植以及太强的平台、软件依赖。

    但是我也不赞同使用用另一个更复杂的概念来解释,这只会让读者更浆糊。如果两者选择,我倾向于使用汇编。

    前缀型++和后缀型++相对在C语言中的应用并不广泛,如果不在表达式中使用,它们基本上是一样的。而我个人也不建议++混在在其他表达式中,比如函数调用作为参数传入也好,作为赋值表达式出现也罢,都有极强的破坏性和副作用,最好的规则就是,++只要单独运行,无论前后。

论坛徽章:
0
170 [报告]
发表于 2010-12-21 11:41 |只看该作者
本帖最后由 KBTiller 于 2010-12-21 11:43 编辑
回复  KBTiller


    我对这段解释的看法是,为了解释++,键盘农夫不得不在一开始就引入更为难懂的概念 ...
sagasw 发表于 2010-12-21 10:21



    首先,我对sagasw网友认真地阅读拙著表示感谢(也许,按照sagasw的风格,应该先谢国家)
    其次,对sagasw网友对拙著的推介(http://www.cnblogs.com/lua5/archive/2010/12/16/1908288.html)表示感谢。(说心里话,确实还感到有些惶恐)
    第三,作为我个人,我更加感谢sagasw网友不辞辛苦、用了大量个人时间和精力对拙著提出的批评意见。这些意见,无论是我现在就接受的还是将来我可能接受的,对于我来说都是无比珍贵的。我为拙著能得遇这样一位对技术精益求精的方家读者而感到庆幸。

    写书的一个难点是不容易确定读者知道什么不知道什么,尤其是对这样一本读者区间跨度很大的书来说,更是如此。这是我写作过程中的一个体会。我愿意在此披露一下当时这样处理的考虑,欢迎大家评议。
    左值的概念,在我看来是至关重要的,是真正理解C的前提。从指针那章来看,不理解左值几乎就无法读下去。
    而且我认为左值这个概念恰恰是多数书籍没有真正讲清楚的,这就是为什么多数人学不好C语言的原因之一
    至于放在何处介绍,我认为是越早越好(当然前面可以浅释,后面应该更严谨全面)。因为如果不了解左值这个概念,我觉得
  
  1. int i=6;
  2. i = i + 2 ;
复制代码

   连“i = i + 2”这样的表达式都无法真正彻底地讲清楚。事实上这个表达式中的两个 “i” 的含义明显是不同的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP