C语言的缺陷与陷阱(一)

目录

前言:

第一章:词法陷阱

1.1 = 不同于 ==

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

1.3 词法分析中的贪心法 

贪心法的介绍

补充知识

1.4 整型常量

1.5 字符与字符串

小补充:

前言:

        在阅读一个英文句子时,我们并不去考虑组成这个句子的单词中单个字母的含义,而是把单词作为一个整体来理解,这是因为字母本身并没有什么意义,我们总是将字母组成单词,然后给单词赋予一定的意义,对于C语言或其它语言编写的程序,道理也是一样的,程序中的单个字符孤立来看并没有什么意义,只有结合上下文才有意义......

第一章:词法陷阱

1.1 = 不同于 ==

=在C语言中是赋值操作符,==在C语言中是比较运算符

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

&在C语言中是取地址操作符或按位与操作符、|在C语言中是按位或运算符

&&在C语言中是逻辑与运算符,||在C语言中是逻辑或运算符

与运算符相关的内容可以查看这篇内容:C语言进制转换、操作符详解

1.3 词法分析中的贪心法 

贪心法的介绍

        C语言的某些符号,例如*、/、和=,只有一个字符,称为单字符符号,而C语言中的其它符号,例如/*、==、和标识符,包括了多个字符,称为多字符符号,当C编译器读入一个/字符后又跟了一个字符*,那么编译器就必须做出判断,是将其作为两个分别的符号对待,还是合起来作为一个符号对待?

        C语言对这个问题的解决方案是:每一个符号应该包含尽可能多的字符,即从左到右逐字符的读入,如果该字符可能组成一个符号,那么再读入的下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分,如果可能,继续读取下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号

        这样的处理策略被称为"贪心法"或者“大嘴法”

 例如:

1、a---b 与 a-- - b含义相同,而与a - -- b不相同

2、我们想要用x除以p指针所指向的值然后将所得的商赋值给y,但是/*被编译器理解为一段注释的开始,编译器会不断的读入字符,直到*/出现为止,也就是说该语句直接将x的值赋给y,根本不会顾及后面的p:

//错误写法
y = x /* p   /* p指向除数*/

//正确写法
y = x / *p   /* p指向除数*/

或
y = x / (*p)   /* p指向除数*/

补充知识

1、需要注意的是,除了字符串与字符常量外,符号的中间不能嵌有空白(空格符、制表符和换行符),例如:==是单个符号,而= =则是两个符号

1.4 整型常量

如果一个整型常量的第一个字符为0,那么该常量将被视为八进制。因此,10与010的含义截然不同。注意!ANSC I标准禁止把8和9作为八进制数字处理,因为许多C编译器会这样做,此外还需要注意的是有时候为了上下文的格式对齐,我们可能无意中将十进制数写成了八进制数:

struct 
{
    int part_number;
    char *description;
}parttab[] = {
    046,  "left"  ,
    047,  "right" ,
    125,  "mid"   ,
};

//parttab是一个结构体变量

1.5 字符与字符串

        C语言中的单引号与多引号含义完全不同,在某些情况下如果把两者弄混,编译器并不会检测报错,从而在运行时产生难以预料的结果。

        用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。因此,对于该字符在编译器采用的字符集中的序列值。因此,对于采用ASCII字符集的编译器而言,‘a’的含义与0141(八进制)或97(十进制)相同。

        用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为0的字符'\0'初始化。

//语句一:
printf("hello world\n");

//语句二:
char hello[] = {'h','e','l','l','l',' ',
                'w','o','r','l','d','\n',0};
printf(hello);

//语句一与语句二等效

        因为单引号括起的一个字符代表整数值,双引号括起的一个字符代表一个指针,如果两者混用,那么编译器的类型检查功能会检测到错误:

//报错
char *slash = ‘/’;

小补充:

在16位或32位的机器中int类型的数的存储空间可以容纳多个字符,因此有的C编译器允许在一个字符常量(以及字符串常量)中包括多个字符,即‘yes’代替“yes”不会被该编译器检测到,后者的含义是依次包含‘y’、‘e’、‘s‘以及空字符'\0'的四个连续内存单元的首地址;对于前者的含义,大多数C编译器理解为“一个整数值,由’y‘、’e‘、’s’ 所代表的整数值按照特定编译器实现中定义的方式组合得到“,因此,这两者如果在数值上有什么相似之处,也仅仅只是巧合。

~over~

你可能感兴趣的:(c语言,c++,开发语言)