| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 893 人关注过本帖
标题:验证2件事情:
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
6.11 为什么有那么多关于空指针的疑惑?为什么这些问题如此经常地出现?
C 程序员传统上喜欢知道很多 (可能比他们需要知道的还要多) 关于机器实现的细节。 空指针在源码和大多数机器实现中都用零来表示的事实导致了很多无根据的猜测。 而预处理宏 (NULL) 的使用又似乎在暗示这个值可能在某个时刻或者在某种怪异的机 器上会改变。``if(p == 0)" 这种结构又很容易被误认为在比较之前把 p 转成了整 数类型, 而不是把 0 转成了指针类型。最后, 术语 ``空" 的几种用法 (如上文 问题 5.10 所列出的) 之间的区别又可能被忽视。
冲出这些迷惘的一个好办法是想象 C 使用一个关键字 (或许象 Pascal 那样, 用  ``nil") 作为空指针常数。编译器要么在源代码没有歧义的时候把 ``nil" 转成适 当类型的空指针, 或者有歧义的时候发出提示。现在事实上, C 语言的空指针常 数关键字不是 ``nil" 而是 ``0", 这在多数情况下都能正常工作, 除了一个未加修饰 的 ``0" 用在非指针上下文的时候, 编译器把它生成整数 0 而不是发出错误信息, 如果那个未加修饰的 0 是应该是空指针常数, 那么生成的程序不行。

授人以渔,不授人以鱼。
2012-12-20 21:29
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
17.5 程序在一台机器上执行完美, 但在另一台上却得到怪异的结果。更奇怪的是, 增加或去除调试的打印语句, 就改变了症状……
许多地方有可能出错。下面是一些通常的检查要点: •未初始化的局部变量, 参见问题 7.1。


•整数上溢, 特别是在一些 16 比特的机器上, 一些中间计算结果可能上溢, 象 a * b / c, 参见问题 3.11。


•未定义的求值顺序, 参见问题 3.1 到 3.5。


•忽略了外部函数的说明, 特别是返回值不是 int 的函数, 或是参数  ``缩小" 或可变的函数。参见问题 1.8, 11.4 和 15.1。


•复引用空指针, 参见第 5 章。


•malloc/free 的不适当使用: 假设 malloc 的内存都被清零、 已释放的内存还可用、再次释放已释放内存、malloc 的内部被破坏, 参见 问题 7.16 和 7.17。


•指针类常规问题, 参见问题 16.7。


•printf() 格式与参数不符, 特别是用 %d 输出 long int, 参见问题 12.7。


•试图分配的内存大小超出一个 unsigned int 类型的范围, 特别是在内存有限的机器上, 参见问题 7.14和 19.27。


•数组边界问题, 特别是暂时的小缓冲, 也许用于 sprinf() 来构造一个字符串, 参见问题 7.1 和 12.19。


•错误的假设了 typedef 的映射类型, 特别是 size_t。


•浮点问题, 参见问题 14.1 和 14.4。


•任何你自己认为聪明的在特定机器上的机器代码生成小技巧。
正确使用函数原型说明能够捕捉到一些以上的问题。lint 会捕捉到更多。 参见问题 16.3, 16.4 和 18.4。

授人以渔,不授人以鱼。
2012-12-20 21:40
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
9.4 我怎么得到对应字符的数字 (字符集) 值, 或者相反?
在 C 语言中字符用它们的字符集值对应的小整数表示。因此, 你不需要 任何转换函数: 如有你有字符, 你就有它的值。
数字字符和它们对应的 0-9 的数字之间相互转换时, 加上或减去常数 '0', 也就是说, '0' 的字符值。

参见问题 13.1 和 20.8。

授人以渔,不授人以鱼。
2012-12-20 21:48
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
14.1 怎样把数字转为字符串 (与 atoi 相反)?有 itoa() 函数吗?
用 sprintf() 就可以了。不需担心用 sprintf() 会小题大作, 也不必担心 会浪费运行时间或代码空间; 实践中它工作得挺好。 参见问题 7.6 答案中的实例; 以及问题 8.4 和 12.19。
你也可以用 sprintf() 把长整形或浮点数转换成字符串 (使用 %ld 或  %f)。

参考资料: [K&R1, Sec. 3.6 p. 60]; [K&R2, Sec. 3.6 p. 64]。

授人以渔,不授人以鱼。
2012-12-20 21:49
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
21.8 怎样转换整数到二进制或十六进制?
确定你真的知道你在问什么。整数是以二进制存储的, 虽然 对于大多数情况下, 把它们当成是八进制、十进制或十六进制 并没有错, 只要方便就好。数字表达的进制只有在读入或写出 到外部世界时才起作用。
在源程序中, 非十进制的数字由在前的 0 或 0x 表示 (分别位 八进制和十六进制)。在进行 I/O 操作时, 数字格式的进制在  printf 和 scanf 这类函数里, 由格式符决定  (%d, %o 和 %x 等); 在  strtol() 和 strtoul() 中, 则由他们的第三 个参数决定。 如果你想要输出任意进制的数字字符串, 你需要 自己提供相关的函数 (基本上是 strtol 的反函数)。 在进行二进制 I/O 时, 进制就不相干了。

更多的有关二进制的 I/O, 参见问题 2.9。还有问题  8.4 和 13.1。

参考资料: [ISO, Secs. 7.10.1.5,7.10.1.6]。

授人以渔,不授人以鱼。
2012-12-20 21:50
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
4.2 使用我的编译器,下面的代码  int i=7; printf("%d\n", i++ * i++); 返回 49?不管按什么顺序计算, 难道不该打印出56吗?
尽管后缀自加和后缀自减操作符 ++ 和 -- 在输出其旧值之后 才会执行运算, 但这里的``之后"常常被误解。没有任何保证 确保自增或 自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进 行。也不能保证变量的更新会在表达式 ``完成" (按照 ANSI C 的术语, 在下一个 ``序列点" 之前, 参见问题 3.7) 之前的某个时刻进行。 本例中, 编译器选择使用变量的旧值相乘以后再对二者进行自增运算。
包含多个不确定的副作用的代码的行为总是被认为未定义。(简单而言, ``多个不确定副作用" 是指在同一个表达式中使用导致同一对象修改两 次或修改以后又被引用的自增, 自减和赋值操作符的任何组合。这是一 个粗略的定义; 严格的定义参见问题 3.7, ``未定义" 的含义 参见问题 11.32。) 甚至都不要试图探究这些东西在你的编译 器中是如何实现的 (这与许多 C 教科书上的弱智练习正好相反); 正如  K&R 明智地指出, ``如果你不知道它们在不同的机器上如何实现, 这样的无知可能恰恰会有助于保护你。begintex2html_deferred

参考资料: [K&R1, Sec. 2.12 p. 50]; [K&R2, Sec. 2.12 p. 54]; [ISO, Sec. 6.3]; [H&S, Sec. 7.12 pp. 227-9]; [CT&P, Sec. 3.7 p. 47]; [PCS, Sec. 9.5 pp. 120-1]。

授人以渔,不授人以鱼。
2012-12-20 21:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
4.5 我可否用括号来强制执行我所需要的计算顺序?
一般来讲, 不行。 运算符优先级和括弧只能赋予表达是计算部分的顺序. 在如下的代码中
     f() + g() * h()

尽管我们知道乘法运算在加法之前, 但这并不能说明这三个函数 哪个会被首先调用。
如果你需要确保子表达式的计算顺序, 你可能需要使用明确的临时 变量和独立的语句。

参考资料: [K&R1, Sec. 2.12 p. 49, Sec. A.7 p]; [K&R2, Sec. 2.12 pp. 52-3, Sec. A.7 p. 200.]。

授人以渔,不授人以鱼。
2012-12-20 22:02
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
13.23 如何清除多余的输入, 以防止在下一个提示符下读入? fflush(stdin) 可以吗?
fflush() 仅对输出流有效。因为它对 ``flush" 的定义是用于完成缓 冲字符的写入, 而对于输入流 fflush 并不是用于放弃剩余的输入。
参考资料: [ISO, Sec. 7.9.5.2]; [H&S, Sec. 15.2]。

授人以渔,不授人以鱼。
2012-12-20 22:05
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
13.24 既然 fflush() 不能, 那么怎样才能清除输入呢?
这取决于你要做什么。如果你希望丢掉调用 scanf() (参见问题 12.16 - 12.17) 之后所剩下的换行符和未预知的输入, 你可能需要重写你的  scanf() 或者换掉它, 参见问题 12.18。或者你可以用下边这样 的代码吃掉一行中多余的字符
     while((c = getchar()) != '\n' && c != EOF)
        /* 丢弃 */ ;

你也可以使用 curses 的 flushinp() 函数。
没有什么标准的办法可以丢弃标准输入流的未读取字符, 即使有, 那也不够, 因为未读取字符也可能来自其它的操作系统级的输入缓冲区。如果你希望严格 丢弃多输入的字符 (可能是预测发出临界提示), 你可能需要使用系统相关的 技术; 参加问题 19.1 和 19.2。

参考资料: [ISO, Sec. 7.9.5.2]; [H&S, Sec. 15.2]。

授人以渔,不授人以鱼。
2012-12-20 22:08
yaobao
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:4
帖 子:1854
专家分:4121
注 册:2012-10-25
收藏
得分:0 
T版,要坚持啊,你贴一张,我复制一张,

认认真真的学习,踏踏实实的走路:戒骄戒躁!!!
2012-12-20 22:17
快速回复:验证2件事情:
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025637 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved