美文网首页
C语言中的词法陷阱

C语言中的词法陷阱

作者: 王伯卿 | 来源:发表于2018-07-03 08:03 被阅读0次

该文章为笔记,因此许多内容摘抄自《C陷阱与缺陷》。
《C陷阱与缺陷》,全书不厚,但是感觉十分有提醒与启迪作用,值得阅读。是打好良好C语言基础的必读手册之一。

1.1 =不同于==

C语言使用 = 作为赋值运算,使用 == 作为比较运算。这两者有巨大的差别。当我们在实际使用的时候,往往会出现如下的错误。

  // example 1
  if(x = y)
   break;

我们本意是用x与y来比较从而来控制程序的进退,但是这里将会进入一个死循环。

当我们误将比较运算写成赋值运算的时候,会出现意想不到的问题。

   //example 2
   while(c = ' ' || c == '\t' || c == '\n')
    c = getc(f);

本例中的循环语句的本意是跳过文件中的空格符、制表符和换行符。
由于在比较 ' ' 和变量c的时候,误将比较运算符==写成了赋值运算符= 。因为赋值运算符=的优先级低于逻辑运算符 || ,因此实际上是将以下表达式的值赋值给了c。

' ' || c == '\t' || c == '\n'

' ' 永远为真,所以上述表达值的求值永远为1,所以程序将会进入一个四循环中。

当我们把比较运算符误写成赋值运算符的时候,同样将会出现编译器无法捕捉的错误。

if((filedesc == open(argv[i], 0)) < 0) 
  error();

本例中,如果open函数执行成功,将会返回0或正数,执行失败,将会返回-1。本例的本意是将open的返回数与filedesc比较,二者比较的结果与0相比判断程序是否错误。暂时不思考filedesc中存储的是什么值,比较运算符==的最后结果只可能是0或-1,因此结果永远都不可能小于0,因此这个error函数,将没有被机会执行。
这是一个隐藏的错误,编译器不会报任何错误,因为在它看来,这是一个符合规则的合法程序。

1.2 & 和 | 不同于 && 和 ||

这里的具体内容,将在稍后补充。

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

原则为每个符号应该包含尽可能多的字符。编译器从左到右读取每一个字符,读了一个再读一个判断是否可以构成一个有意义的字符。我们可以看下面这个例子。

y = x/*p;

大家看颜色可以发现,读到/,再读下一个,发现是,因此编译器认为这个是注释的开头,因此接下里编译器就不断的往下读取,直至出现/为止。
因此,这里推荐,抓不准的时候,请一定要加上括号。

  y = x/(*p);

然后我们看下比较变态的例子。

#include <stdio.h>

int main(void){
  int a = 3;
  int b = 5;
  int sum = a+++b;
  printf("%d,%d,%d\n",a,b,sum);
}
//4,5,8

最后输出4,5,8。这里做一个词法分析。
1)读入a,读入下一个
2)读入+,读入下一个
3)读入+,两个+,当成自增符号++使用,左结合给a,因此左边为a++
4)读入+,读入下一个
5)读入b,前面的+当作加法来算
因此就是(a++)+b。

假设我们往a+++b里多加几个+,变成诸如a+++++b,这样编译器会报错。因为a++ 后在读入两个+,编译器认为是自增符号因此左结合给a++,然而a++后不能在自增了,因此程序报错。

但是如果我们添加空格,比如这样a+++ ++b,这样就可以编译通过了,因为编译器在读取第三个+后,再往后读取一个,发现是空格,所以就把第三个+当作加号来使用,编译就通过了。

这些题,完全没有意义。建议使用的时候加括号,然后部门中如果出现这么写的人,建议早点把他辞退。

1.4 整型常量

这里需要注意,如果一个整型常量的第一个字符是数字0,那么该常量将被视作八进制数。

1.5 字符与字符串

用单引号引起的一个字符实际上代表一个一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。
用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针。
这里只简单举一个例子。

# include <iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    char str1 = 'A';
    int str2 = 65;
    cout<<str1<<endl<<(char) str2<<endl;
    return 0;
}

最后会输出两个A。

相关文章

  • C语言中的词法陷阱

    该文章为笔记,因此许多内容摘抄自《C陷阱与缺陷》。《C陷阱与缺陷》,全书不厚,但是感觉十分有提醒与启迪作用,值得阅...

  • C语言陷阱「词法陷阱 之字符与字符串」

    C语言陷阱【词法陷阱 之字符与字符串】 字符与字符串 C语言中的单引号' ',与双引号" ",含义不同。 用单引号...

  • 第一章

    c陷阱与缺陷的读后总结第一章 关于词法“陷阱”(主要讲符号和组成符号的字符间的关系以及一些常见错误)新定义符...

  • 【C 陷阱与缺陷 学习笔记】(一)词法陷阱

    码字不易,对你有帮助 点赞/转发/关注 支持一下作者微信搜公众号:不会编程的程序圆看更多干货,获取第一时间更新代码...

  • Java中的断言assert

    Java陷阱之assert关键字 一、概述 在C和C++语言中都有assert关键,表示断言。在Java中,同样也...

  • 第二章

    词法“陷阱” 2.1 理解函数声明 任何C变量的声明都由两部分组成;类型以及一组类似表达式的声明符。理解(*(v...

  • C语言基础6

    结构体概述 1 在C语言中,结构体(struct)指的是一种数据结构,是C语 言中构造类型的其中之一。 2 在实际...

  • OC简介

    OC与C对比 1. 源文件对比 C语言中常见源文件.h头文件,.c文件.h 头文件,用于存放函数声明.c C语...

  • 读 《C Traps and Pitfalls》Record

    @(C 语言)[基础, 编程] 薄薄一本书, 却记录了c 编程经常犯下的错误,再读,记录下。 词法 词法分析 : ...

  • 【二】词法分析 re2c

    re2c PHP做词法分析用的是re2c,之前使用的是lex,Mysql的词法分析也是用的re2c。re2c和le...

网友评论

      本文标题:C语言中的词法陷阱

      本文链接:https://www.haomeiwen.com/subject/qzxtuftx.html