zoukankan      html  css  js  c++  java
  • [C陷阱和缺陷] 第1章 词法“陷阱”

    有感自己的C语言在有些地方存在误区,所以重新仔细把《C陷阱和缺陷》一书翻出来看看,并写下这篇博客,用于读书总结以及日后方便自身复习。

    第1章 词法“陷阱”


    1.1 =不同与==

    =是赋值操作符,而==是作为比较操作符,初学者容易将==错写为=,这种情况下编译器不会报错,这就有可能造成很严重的后果,还不容易发现。比如下面这个例子:

    while( c=' ' || c=='	' || c=='
    ' )  { ; } 
    

    即使 c 既不等于' ',也不等于' ',但由于' '赋给 c,' '不为 0,所以 while 始终为真,成为死循环。所以有时采取下面这张写法,就能尽可能地避免这种错误(个人不太喜欢),即使错写为=,编译器也会报错进行提醒:

    while( ' '=c || '	'==c || '
    '==c )  { ; }
    

    1.2 词法分析中的“贪心法”

    当编译器读入一个字符'/'后又跟了一个字符'*'那么编译器就必须做出判断:是将其作为两个独立的符号对待,还是合并起来作为一个符号对待。C语言对这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多的字符。

    也就是说,编译器将程序分解成符号的方法是,从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断两个读入字符合并成的字符串是否可能是一个字符的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个策略有时被称为“贪心法”。

    需要注意的是,除了字符串和字符常量,符号的中间不能嵌有空白(空白、制表符、换行符)。例如,==是单个符号,= =是两个符号,表达式a---b与 表达式a -- - b的含义相同,与表达式a - --b的含义不同。看下面这个例子:

    y = x/*p; // x除以p指向的内容
    

    而实际上,/*被编译器理解为一段注释的开始,也就是说,该语句会将x之间赋给y,后面全是注释。必须这么写才对:

    y = x / *p; // 正确
    

    或者更加清楚一点,使用括号:

    y = x/(*p); //正确
    

    1.3 整型常量

    如果一个整型变量的第一个字符是数字0,那么该常量将被视为八进制数。因此,10010的含义完全不同。例如,0195的含义是1*8^2 + 9*8^1 + 5*8^0,也就是141(十进制)或者0215(八进制)。

    需要注意这种情况,有时候在上下文中为了格式对齐的需要,可能无意间将十进制数写成了八进制数,例如:

    struct
    {
    	int    part_number;
    	char    *description;
    } porttab[ ] = {
    	046, "left-handed widget" ,
    	047, "right-handed widget" ,
    	125, "frammis"
    }
    

    1.4 字符与字符串

    C语言中的单引号和双引号含义完全不同,用单引号引起的一个字符实际上表示一个整数,例如'a'的含义与97(十进制)严格一致。而即使是用双引号引起的一个字符,也是指向一个无名数组首个字符的指针,该数组被双引号之间的字符以及字符''初始化。

    下面的这个语句:

    printf("Hello world
    ");
    

    char hello[ ] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '
    ' };
    

    是等效的。

    因为用单引号引起的一个字符代表一个整数,而用双引号引起的一个字符代表一个指针,所以两者不能混用,否则编译器的类型检查功能将会检查到错误:

    char *p = 'a'; // error!
    

  • 相关阅读:
    GNU软件FTP下载汇总
    设置git的代理服务器
    今天发现一个Convert.ToDateTime的异常,算不算微软的bug呢?
    无线电空间传输损耗衰减计算(转帖)
    使用ArcGis10.2通过Dem提取山顶点(原创)
    VC++编译zlib
    VC++编译libpng
    vc++编译libtiff4.0.4
    VC++编译GSL
    libCEF总结02字符串
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/9949193.html
Copyright © 2011-2022 走看看