IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言陷阱与缺陷 之 词法 -> 正文阅读

[C++知识库]C语言陷阱与缺陷 之 词法

前言

本文主要参考Andrew Koenig 的《C Traps and Pitfalls》,重新编排整理,归纳总结了C语言编程中常见的问题点,并提出了一些简单的意见和建议,以期读者阅读本文后,能够在编程实践中做出预防性的设计,减少因语言理解不到位而产生的Bug。让我们站在巨人的肩膀上前进,而不是陷在巨人的脚印里挣扎,愿与诸君共勉。


目录

前言

一、相似符号

二、贪心法

三、八进制

四、字符与字符串

五、优先级与结合性

参考资料


一、相似符号

在C语言中有几对长得很相似符号,如:= 和 ==、| 和 ||、& 和 &&,其潜在的问题在于,程序员很容易无意中将这些符号误写成对方的模样,而且大多数情况是无法通过编译报错发现的。

代码1.1 误写判等符

int x = 2;
int y = 3;

bool func(int x, int y)
{
    bool res = false;

    if (x = y) {
        res = true;
    }

    return res;
}

可以看出上边这段代码的原意是要在参数相等的时候返回真,但由于将 == 误写了 =,实际就成了判断y是不是0。现在的编译器一般可以识别出判断表达式中 = 和 == 的区别,并通过告警信息显示出来,但如果考虑兼容编译器版本,则还是应改做一些规定和处理:

  • 判断表达式中不要进行赋值操作
  • 变量和常量判等时,常量放在符号左边
  • 两个变量判等时,生命周期长的变量放在符号右边

扩展的讲,最好不要在判断表达式中进行带有“副作用”的操作,比如自增、自减甚至是运算赋值,这会增加程序理解的复杂度,同时很容易引入问题。

常量放在 == 左边可以避免误写为 = 的情况,此时编译器一定会报错。不同于 > 和 < 判断,判等符的左、右值是什么,并不会影响程序的阅读。

生命周期长的变量放在 == 右边,是考虑在误写时降低影响面,便于定位问题;但有些情形下,也可能会掩盖问题的发现,因此还要结合实际业务场景,区别对待。

| 和 ||、& 和 && 与 = 和 == 的问题大致相同。要想避免误写,除了仔细仔细再仔细外,可以做的一点是:

  • 用 or 替换 ||
  • 用 and 替换 &&

如同用 uint 替换 unsigned int 一样,借鉴其他语言,使用文本替换,降低误写的概率。

另外,/ 和 // 在形式上似乎和上述几种情形相似,但实际上却有一个明显的差别,即误写时很容易在编译阶段发现,因而不再作进一步讨论。

二、贪心法

C编译器读取多字符符号(//、/*、==)时,为了准确的识别出符号,会从左到右逐个读入字符,直到读取的字符不能再组成一个有意义的符号时停止,稍有不慎就会产生一句代码两个意思的情况。

代码2.2 准二义性语句

int func(int x, int *p)
{
    if (*p == null) {
        return -1;
    }
    
    int res = x/*p /* p指向除数 */;
    
    return res;
}

代码2.2展示了一种准二义性的语句,其原意是要求商。但由于编译器识别到第一个 / 后,会根据贪心法继续向后读取,一直到最后一个 / 才结束,对编译器而言就变成了返回x的值。针对这种情况:

  • 运算符号左右需要各空一个空格
  • 使用括号明确运算优先级

在运算符左右各空一个空格,除了使代码美观、易读之外,还具有分割字符的作用,如将代码2.2改为代码2.3的形式,语义就正确了。

代码2.3

int func(int x, int *p)
{
    if (*p == null) {
        return -1;
    }
    
    int res = x / *p /* p指向除数 */;
    
    return res;
}

使用括号显式的标明运算符的优先级,而不过度依赖运算符自身的结合性和优先级,可以减少错误,并且易于阅读,将代码2.2之改为代码2.4的形式,语义也能正确。

代码2.4

int func(int x, int *p)
{
    if (*p == null) {
        return -1;
    }
    
    int res = x/(*p) /* p指向除数 */;
    
    return res;
}

针对代码2.2这个具体的例子,使用带有主题颜色区分功能的代码编辑器也能明显的发现问题,当然也还可以有另外一些规则,如:

  • 注释只能加在语句上边或右边

三、八进制

在C语言中整型常量有八进制、十进制和十六进制三种表示方法,为了上下文对齐会无意中将十进制的数改成八进制形式,如:

代码3.1

int array[] = {
    123,
    125,
    024,
};

?其中024是八进制数,对应十进制的值是20,这种情况下一般可以采用空格对齐。

四、字符与字符串

在C语言中,用单引号引起来的一个字符实际代表一个整数,而用双引号引起来的字符串,代表的是一个指向无名数组起始字符的指针。两者混用,会引发一些显式的错误,如:

代码4.1

char *buf = '3';

此时编译器会报错,因为 '3' 是一个整数;而 "3" 就是正确的,它代表的是一个包含结束符的字符串常量。

五、优先级与结合性

附上C语言运算符优先级与结合性明细表,以备查览。

表5.1 运算符优先级与结合性

运算符

名称或含义

优先级

结合性

[]

数组下标

1

从左到右

()

圆括号

.

成员运算符

->

成员运算符

-

负号

2

从右到左

~

按位取反

++

自增

--

自减

*

取值

&

取地址

!

逻辑非

(类型)

强制类型转换

sizeof

获取字节大小

/

3

从左到右

*

%

取余

+

4

从左到右

-

<<?

左移

5

从左到右

>>?

右移

>?

大于

6

从左到右

>=

大于等于

<?

小于

<=

小于等于

==

等于

7

从左到右

!=

不等于

&

按位与

8

从左到右

^

按位异或

9

从左到右

|

按位或

10

从左到右

&&

逻辑与

11

从左到右

||

逻辑或

12

从左到右

?:

条件运算符

13

从右到左

=

赋值

14

从右到左

/=

除后赋值

*=

乘后赋值

%=

取余后赋值

+=

加后赋值

-=

减后赋值

<<=

左移后赋值

>>=

右移后赋值

&=

按位与后赋值

^=

按位异或后赋值

|=

按位或后赋值

逗号运算符

15

从左到右


参考资料

  1. 《C Traps and Pitfalls》[美]Andrew Koenig著
  2. C语言运算符优先级(超详细)_良师,益友-CSDN博客_c语言优先级运算符

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-02 14:26:18  更:2021-10-02 14:27:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 3:57:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计