网站大量收购独家精品文档,联系QQ:2885784924

《C陷阱与缺陷》笔记.doc

  1. 1、本文档共14页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
?第1章 词法“陷阱”? 1.1 = 不同于 == == 为比较运算符, = 为赋值运算符 例:?while( c = || c == \t || c == \n ) ?? c = getc( f );??? 本意是c和 比较,但错用成赋值符。这样的后果是将 || c == \t || c == \n 这个表达式的值给了c, 而使c = 1。??? 同样: if ( ( filedesc == open( argv[i], 0 ) ) 0 ) error();??? open的返回值和filedesc比较的结果只能是0或1,所以,error没有机会调用。但是,此时filedesc的值于open返回值无关,编译器这里不会报错。容易被忽视,达不到检查效果。 1.2 和 | 不同于 和 || 和|均为按位运算符,而 和 || 均为逻辑运算符,不能混淆。 1.3 语法分析中的“贪心法” 当C编译器读入一个字符后又跟了一个字符,那么编译器就必须做出判断:是将其作为两个分别的符号对待,还是合起来作为一个符号对待。C语言对这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多的字符。 a---b 与 a -- - b 的含义相同,而与 a - -- b 的含义不同。 1.4 整型常量 如果一个整形常量的第一个字符是数字0,那么该常量将被视作八进制数。因此,10和010是完全不同的含义。此外书中还介绍了一些ANSI C不允许的做法,比如将8和9也作为八进制数字处理。 1.5 字符和字符串 C语言中的单引号和双引号含义迥异,在某些情况下如果把两者弄混,编译器并不会检测报错,从而在运行是产生难以预料的结果。 用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。 用双引号引起的字符串,代表的却是一个指向无名数字起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制为零的字符初始化。 然而,某些C编译器对函数参数并不进行类型检查,特别是对printf函数的参数。因此, 如果用 printf( ); 来代替正确的 printf( ); 则会在程序运行的时候产生难以预料的错误,而不会给出编译器诊断信息。 整型数(一般为16位或32为)的存储空间可以容纳多个字符(一般为8位),因此有个C编译器允许在一个字符常量(以及字符串常量)中包括多个字符。也就是说,用yes代替yes不会被该编译器检测到。后者的含义是“一次包括yes以及空字符的4个连续内存单元的首地址“。前者的含义并没有准确的进行定义,但大多数编译器理解为,“一个整数值,由yes所代表的整数值按照特定编译器实现中定义的方式组合得到“。 (注:在Borland C++ v5.5 和 LCC v3.6中采取的做法是,忽略多余的字符,最后的整数值即第一个字符的整数值;而在Visual C++ 6.0 和 GCC v2.95中采取的做法是,依次用后一个字符覆盖前一个字符,最后得到的整数值即最后一个字符的整数值。) 第2章:语法“陷阱” 2.1 理解函数声明 (*(void(*)())0) (); 任何复杂表达式其实只有一条简单的规则:按照使用的方式来声明。 任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符(declarator)。声明符从表面上看与表达式有些类似,对它求值应该返回一个声明中给定类型的结果。 因为声明符与表达式的相似,所以我们也可以在声明符中任意使用括号: float ((f)); 这个声明的含义是:当对其求值时,((f))的类型为浮点类型,由此可以推知,f也是浮点类型。 各种形式的声明还可以组合起来,就像在表达式中进行组合一样。因此, float *g(),(*h)()表示*g()与(*h)()是浮点表达式。因为()结合优先级高于*,*g()也就是*(g()):g是一个函数,该函数的返回值类型为指向浮点数的指针。同理,可以得出h是一个函数指针,h所指向函数的返回值为浮点类型。 一旦我们知道了如何声明一个给定类型的变量,那么该类型的类型转换符就很容易得到了:只需要把声明中的变量名和声明末尾的分号去掉,再将剩余的部分用一个括号整个“封装”起来即可。例如,因为下面的声明: float (*h)(); 表示h是一个指向返回值为浮点类型的函数的指针,因此,(float (*)())表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。 (*fp)(); - (*0)(); - (*(void (*)())0)(); 2.2 运算符的优先级问题 优先级最高者其实并不

文档评论(0)

enxyuio + 关注
内容提供者

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

1亿VIP精品文档

相关文档