C陷阱与缺陷 C Traps and Pitfalls.docVIP

  1. 1、本文档共24页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C陷阱与缺陷 C Traps and Pitfalls.doc

? C缺陷和陷阱 ?述 c语言就像一把餐刀:简单、锋利并且在老手手中威力无穷。和所有锋利的工具一样,c会对那些不懂得如何去操控他的人造成伤害。本文介绍c各种可能会对粗心的人造成伤害的情况并且告诉你如何去避免伤害。? 0.绪论 c语言和它的典型实现都是为了专家可以很容易的使用而设计的。它简洁并且传神,它只有很少的约束来防止用户犯一些粗心的错误。一个粗心的使用者经常会得到一些不明原因的结果。 在本文中,我们会看到一些意想不到的异常。因为他们都是不可预见的,所以很难去完全的区分这些异常的原因。然而,我们通过观察c语言程序运行时发生的变化得到了一个大概的结论。我们假设读者至少都熟练掌握了c语言。 第一部分主要关注程序被拆分成标记时可能发生的问题。第二部分考虑编译器将标记组织成声明、表达式、语句时可能产生的问题。第三部分指明c程序通常由几个单独编译的部分组成。第四部分处理程序实际运行时出现的语义上的不确定。第五部分将介绍我们的程序和库之间的关系。在第六部分我们知道我们写的程序并不是实际运行的程序:预处理出现。最后、第七部分讨论一个小问题、程序只能运行在具体的一种实现而不能是其他实现的原因。? 1.?词法的缺陷 编译器的第一部分通常是一个词法分析器。它通过分析组成程序的字符序列并将他们分解成一个个的标记。标记是该语言中可被编译的由一个或多个字符组成的序列。例如:在c中,-标记的含义与组成它的每个字符的含义完全不同并且在上下文中出现的每一个-都是可以被独立识别的。 另一个例子,考虑下面这个语句: ??if (x big) big = x; 在这个语句中除了关键字if和两个标志符big之外,每一个非空的字符也都是一个单独的标记。 ????实际上c语言程序被分成两次拆分为标记。首先预处理器处理程序,将程序标记为可识别的标志符,包括一些宏。然后将宏替换为宏的运算结果。最后宏替换后的结果被重新联合到编译器处理的字节流里。编译器再次将这些字节流拆分成标记。 ????在这一节,我们将探讨一些关于标记含义的普遍的误解以及标记与组成标记的字符之间的关系。稍后我们将讨论预处理器。? 1.1?=?不是?== ????像Pascal、Ada这些源自Algol的程序设计语言使用?:=?作为赋值运算符?=?作为比较运算符。另一方面像c使用?=?进行赋值、==进行比较。这是因为赋值运算比比较运算使用的更加频繁,所以更普遍的做法是使用短的符号表示赋值。 ????而且,c把赋值看作一个运算符,因此可以很容易写出多重赋值(例如:a=b=c)并且赋值可以嵌入到大型的表达式里。 ????这种便利导致了一个潜在的问题:当你想写一个比较符号时会不经意把它写成赋值运算符。因此,像以下的语句看着是要比较x是否等于y ????if (x = y) ??????foo(); 实际将y的值赋给x然后判断x的值是否等于0。继续考虑以下的一个循环,它打算过滤一个文件中的空格、tab、以及换行符: ????while (c == ‘ ‘ || c = ‘ ’ || c == ‘ ’ ) ????????c = getc(f); 这个程序在比较c?和?‘ ’的时候误用’=’代替了’==’。这个”比较”实际将’ ’赋给了c并将赋值后的c与0进行比较。’ ’的值并不是0,所以”比较”的结果将始终为真,所以这个循环将会过滤掉整个文件。当一个特定的实现允许程序在读到文件末尾时继续读这个文件,这个循环将会是一个死循环。 ????一些c编译器在条件语句为e1=e2的形式的时候给出警告信息提示使用者。为了避免在使用这样的编译器时出现警告信息,当你想给一个变量赋值并判断这个变量是不是0时考虑采用更加直观的方式来写这个表达式。如使用 ????if ((x=y) != 0) ????????foo(); 代替 ????if(x=y) ??????foo(); 这样的方式能更加清楚的体现您的意图。? 1.2 和|?不是?和|| ????由于很多其他的语言都采用=来作为比较运算符,你很容易忽略这些用=代替了==的错误。由于c中的和|不同于其他语言的以及||,您同样很容易将和?或?|和||互换。我们将在第四节详细介绍这些运算符。? 1.3?多字符标记 ????一些c语言的标记如/, *, =等都只有一个字符的长度,另外的一些c语言标记,如/*, ==以及标志符等都是几个字符长度的。当c的编译器遇到一个/紧跟着一个*时,编译器能够判断这两个字符到底是两个单独的标记还是一个单一的标记。C语言参考手册告诉我们编译器是如何判断的:“如果输入字节流根据一个给定的字符解析成标记,那每一个标记将包含可能组成标记的最长的字符串”。也就是说如果/是一个标记的第一个字符,并且/后紧跟着一个*,这两个字符组成一个注释符号,它忽略它

文档评论(0)

sis_lxf + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档