当前位置: 首页 > news >正文

《C陷阱与缺陷》----词法“陷阱”

导言:

由于一个程序错误可以从不同层面采用不同方式进行考察,而根据程序错误与考察程序的方式之间的相关性,可以将程序错误进行划分为各种陷阱与缺陷:
①.词法“陷阱
②.语法“陷阱”
③.语义“陷阱”
④.连接问题
⑤.库函数问题
⑥.预处理器问题
⑦.可移植性缺陷

我们知道程序是由符号序列所组成的。本篇主要考察在程序被词法分析器分解成各个符号的过程中可能出现的问题,也就是词法“陷阱”。

  • 导言:
  • 1.=不同于==
    • 1.1 案例1
    • 1.2 案例2
    • 1.3 启示
    • 1.4 案例3
  • 2.&和 |不同于&&和 ||
  • 3.词法分析中的“贪心法”
    • 3.1 读取规则---“贪心法”:
    • 3.2 注意:
    • 3.3 “贪心法”读取案例1
  • 4.整形常量
  • 5.字符和字符串
    • 5.1 字符
    • 5.2 字符串
  • 6.练习题
    • 6.1 练习题①
    • 6.2 练习题②

1.=不同于==

符号 =作为赋值运算符
符号==作为比较运算符
由于在C语言中赋值操作相对于比较出现更加频繁,所以将字符较少的符号=赋予更常用的含义—赋值操作。
不过这种便利的使用可能导致一个潜在的问题:当程序员本想使用比较运算符却使用了赋值运算符。

1.1 案例1


if(x=y)
break;

该句的本意是想检查x是否等于y;但实际上却是将y的值赋给了x,然后检查表达式结果是否为0。

1.2 案例2

再比如下面这个例子:
例子中循环语句本想跳过空格符,制表符,和换行号;

   while(i=' '||i=='\t'||i=='\n')i=getchar();

但是却把比较运算符误写成赋值运算符,因为赋值运算符=的优先级是低于逻辑运算符||,所以语句先将’ ‘赋给了i,然后发先i结果不为0(’ 'ASCII码值是32)根据短路求值原则,左边为真,则右边不再进行,此语句也就是真,因此循环将一值进行下去直到整个文件结束。或者变成一个死循环。

1.3 启示

某些C编译器在发现形如a=b的表达式出现在循环语句的条件判断部分时,会给出警告以提醒程序员。当确实需要对变量进行赋值并检查该变量的新值是否为0时,为了避免该类编译器的警告,我们应该进行显式地比较,比如

if(x=y)
{Function();
}

应该写成

if((x=y)!=0)
{Function();
}

这样的写法就使得代码的意图一目了然。

1.4 案例3

前面一直谈的是将比较运算符误写成赋值运算符,另一方面,如果把赋值运算符误写成比较运算符,也会造成混淆。

if ((i == fun(a, b)) < 0)error();

本语句的原本意思是如果fun函数执行成功则返回0,执行失败则返回-1或者正数,然后再将返回值赋给i,通过比较i的大小来确定是否fun函数执行成功。但实际上是fun函数的返回值与i进行比较,结果只有真与假也就是0或1,永远不可能小于0,所以函数error没有机会调用。也就不知道fun函数调用是否失败。

2.&和 |不同于&&和 ||

3.词法分析中的“贪心法”

C语言有许多符号,比如只有一个字符长的单字符符号,和多个字符长的多字字符。比如== 和 /*。
当C编译器读取符号时,是如何读取的呢?

比如读入一个字符’/‘后又跟了一个字符’ *',那编译器是将其作为两个分别的符号对待,还是合起来作为一个符号对待?

3.1 读取规则—“贪心法”:

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

3.2 注意:

需要注意的是,除了字符串与字符常量,符号的中间不能嵌有空白(空格符,制表符和换行符)。
比如:

a---b 与表达式
a-- -b的含义相同,但与
a- --b的含义完全不同。

3.3 “贪心法”读取案例1

本代码想表达的意思是,x先除以指针p指向的数,然后再将所得的商,赋给y.

y=x / *p;// *p指向的是被除数

而实际上,/*被编译器理解为一段注释的开始,编译器将不断的读入字符,直到另一个 * /出现为止。
也就是说该代码,直接将x的值赋给了y,根本不会顾及后面出现的p。

而正确的表达意思应该是这样:

y=x/(*p);//*p指的是被除数

4.整形常量

我们知道一个整形常量第一个字符是数字0,则这个常量代表的是八进制位数。
因此10与010的意思不一样

而有的C编译器会把8,9也作为八进制数字来处理,感觉很奇怪,所以ANSI C标准禁止了这种用法,以免混乱。
不过有时候,在上下文中为了格式对齐,可能会将十进制数写成八进制数。比如:

035
044
123//只是单词的使格式对齐没有多的意思,

5.字符和字符串

C语言中字符与字符串的区别在于单引号与双引号的使用,在某些情况下如果把两者弄混,编译器并不会监测报错,从而运行时产生难以预料的结果。我们先来看看字符与字符串的区别

5.1 字符

用单引号引起的一个字符实际上代表一个整数,整数对应着ASCII码值的字符序列值,比如’a‘的含义与0141(八进制)或者97(十进制)严格一致。

整数(一般为16位或32位)的存储空间可以容纳多个字符(一般位8位)因此有的C编译器允许在一个字符常量(以及字符串常量)中包含多个字符。也就是用‘yes’代替“yes”不会被该编译器监测到。“yes”代表的意思是依次包含‘y’,‘e’,‘s’以及空字符‘\0’的4个练习内存单元的首地址。而‘yes’的含义并没有准确的进行定义,但大多数编译器理解为“一个整数值”
在这里插入图片描述

5.2 字符串

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

#include <stdio.h>
int main()
{printf("xiao tao lai lo\n");char ch[100] = "xiao tao lai lo";//ch是数组名,数组名是首元素的地址,也就是首字符的地址。printf(ch);//ch里存放着首元素的地址}

在这里插入图片描述

这说明这两个打印效果是一样的,所以一个字符串代表着一个指向无名数组起始字符的指针。可以用一个指针来存放字符串

#include <stdio.h>
int main()
{
char* p = "xiao tao lai lo";//指针p里面存放的就是字符串的首字符地址。printf(p);
}

在这里插入图片描述

6.练习题

6.1 练习题①

在这里插入图片描述
答案:
根据“贪心法”规则,在编译器读入>之前,就已经将- -作为一个符号,而后面的>不能和前面的组成一个符号。

6.2 练习题②

在这里插入图片描述

答案:
这个代码唯一有意义的解析是这样:

a++ + ++b

但是根据“贪心法”规则,上面代码应该被分解为

a++ ++ +b

这个式子从语法上来说是不对的,它应该写成

((a++)++)+b

但是,a++的结果不能作为左值,因此编译器不会接收a++作为后面的++运算符的操作数,该代码没有意义

…………………………………………………………请添加图片描述…………………………………………………………
………………………………………………………………………加油…………………………………………………………

相关文章:

《C陷阱与缺陷》----词法“陷阱”

导言&#xff1a; 由于一个程序错误可以从不同层面采用不同方式进行考察&#xff0c;而根据程序错误与考察程序的方式之间的相关性&#xff0c;可以将程序错误进行划分为各种陷阱与缺陷&#xff1a; ①.词法“陷阱” ②.语法“陷阱” ③.语义“陷阱” ④.连接问题 ⑤.库函数问…...

千锋教育+计算机四级网络-计算机网络学习-04

UDP概述 UDP协议 面向无连接的用户数据报协议&#xff0c;在传输数据前不需要先建立连接&#xff1b;目地主机的运输层收到UDP报文后&#xff0c;不需要给出任何确认 UDP特点 相比TCP速度稍快些简单的请求/应答应用程序可以使用UDP对于海量数据传输不应该使用UDP广播和多播应用…...

蓝桥杯算法训练合集十四 1.P08052.P07053.同余方程4.P08015.ascii应用

目录 1.P0805 2.P0705 3.同余方程 4.P0801 5.ascii应用 1.P0805 问题描述 当两个比较大的整数相乘时&#xff0c;可能会出现数据溢出的情形。为避免溢出&#xff0c;可以采用字符串的方法来实现两个大数之间的乘法。具体来说&#xff0c;首先以字符串的形式输入两个整数&…...

判断字符串中的字符的类型isdecimal();isalpha();isdigit();isalnum()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断字符串中的字符的类型 isdecimal()&#xff1b;isalpha()&#xff1b;isdigit()&#xff1b;isalnum() [太阳]选择题 对于代码中isdecimal()和isalnum()输出的结果是? s "ABc123&…...

VSCode远程调试Linux代码,python解释器配置

安装插件并配置 安装后找到插件图标&#xff0c;点击 点击SSH上的 号 在弹出框中输入命令&#xff1a;ssh usernameip -p port username: 远程服务器的用户名 ip&#xff1a; 远程ip port&#xff1a;端口号&#xff0c;没有可以不用 输入完毕后点击enter 选择ssh配置文件保存…...

03:入门篇 - CTK Plugin Framework 基本原理

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 CTK Plugin Framework 技术是面向 C++ 的动态模型系统。该系统允许插件之间的松散耦合,并且提供了设计良好的方式来进行功能和数据的交互。此外,它没有预先对插件施加限制,这样就可以很容易地将插件的相关…...

面试攻略,Java 基础面试 100 问(九)

数组有没有 length()方法?String 有没有 length()方法&#xff1f; 数组没有 length()方法&#xff0c;有 length 的属性。String 有 length()方法。JavaScript 中&#xff0c;获得字符串的长度是通过 length 属性得到的&#xff0c;这一点容易和 Java混淆。 在 Java 中&…...

JavaScript 代码不嵌套主义

文章目录前言一、何为嵌套代码二、避免嵌套1.提炼抽取2.反转排列总结前言 看过不少过度嵌套的代码, 我真正意识到问题的严重性是刚入职那会, 我在一个老项目里看到了40个连续的else if, 套了6层的if, for和forEach, 因为我们并没有做什么限制代码嵌套的提前约定. 呃, 那之后认…...

使用默认参数的4大要点

概述 默认参数是C中新增的特性。在C中&#xff0c;可以为函数的参数指定默认值。调用函数时&#xff0c;如果没有指定实参&#xff0c;则自动使用默认参数。默认参数的基本语法这里就不作介绍了&#xff0c;下面重点介绍使用默认参数的一些知识要点。 基本规则 1、当函数中某个…...

Linux文件系统中的硬链接及常见面试题

如果能对inode的概念有所了解&#xff0c;对理解本文会有所帮助。如果对inode的概念不太清楚也没有关系&#xff0c;我们会捎带介绍一下。在文件系统的实现层面&#xff0c;我们可以认为包含两个组件&#xff1a;一个是包含数据块的池子&#xff0c;池子中的数据块是等大小的&a…...

opencv-StereoBM算法

原理解释目前立体匹配算法是计算机视觉中的一个难点和热点&#xff0c;算法很多&#xff0c;但是一般的步骤是&#xff1a;A、匹配代价计算匹配代价计算是整个立体匹配算法的基础&#xff0c;实际是对不同视差下进行灰度相似性测量。常见的方法有灰度差的平方SD&#xff08;squ…...

图像分类竞赛进阶技能:OpenAI-CLIP使用范例

OpenAI-CLIP 官方介绍 尽管深度学习已经彻底改变了计算机视觉&#xff0c;但目前的方法存在几个主要问题:典型的视觉数据集是劳动密集型的&#xff0c;创建成本高&#xff0c;同时只教授一组狭窄的视觉概念;标准视觉模型擅长于一项任务且仅擅长于一项任务&#xff0c;并且需要大…...

Metasploit框架基础(一)

文章目录前言一、基础认知二、批量POC/EXP的构想三、poc检测框架的简单实现四、xray五、Meatsploit框架参考前言 Metasploit 一款渗透测试框架漏洞利用的集合与构建和定制满足你的需求的基础漏洞利用和验证的工具 这几个说法都是百度或者官方文档中出现的手法&#xff0c;说…...

pytorch零基础实现语义分割项目(二)——标签转换与数据加载

数据转换与加载项目列表前言标签转换RGB标签到类别标签映射RGB标签转换成类别标签数据数据加载随机裁剪数据加载项目列表 语义分割项目&#xff08;一&#xff09;——数据概况及预处理 语义分割项目&#xff08;二&#xff09;——标签转换与数据加载 语义分割项目&#x…...

python(8.5)--列表习题

目录 一、求输出结果题 二、计算列表元素个数 三、查找是否存在某元素 四、删除某元素 五、如何在列表中插入元素 六、如何从列表中删除重复的元素 七、 如何将列表中的元素按照从小到大的顺序排序 八、从列表中删除重复的元素 九、大到小的顺序排序 一、求输出结…...

rt-thread pwm 多通道

一通道pwm参考 https://blog.csdn.net/yangshengwei230612/article/details/128738351?spm1001.2014.3001.5501 以下主要是多通道与一通道的区别 芯片 stm32f407rgt6 1、配置PWM设备驱动相关宏定义 添加PWM宏定义 #define BSP_USING_PWM8 #define BSP_USING_PWM8_CH1 #d…...

C语言练习 | 初学者经典练习汇总

目录 1、下面代码输出多少&#xff0c;为什么&#xff1f; 2、你要好好学习么&#xff1f; 3、一直写代码&#xff0c; 4、两个数求最大值 5、输入1-5输出工作日&#xff0c;输入6-7输出休息日&#xff0c;其他输入错误 6、写一个输入密码的代码 7、怎么样当输入数字时候…...

华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 卡片组成的最大数字(Python) | 机试题算法思路 华为OD机试 - 网上商城优惠活动(一)(Python) | 机试题算法思路 华为OD机试 - 统计匹配的二元组个数(Python) | 机试题算法思路 华为OD机试 - 找到它(Python) | 机试题算法思路 华为OD机试…...

「6」线性代数(期末复习)

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 第五章 相似矩阵及二次型 &2&#xff09;方阵的特征值与特征向量 &3&#xff…...

1.1 硬件与micropython固件烧录及自编译固件

1.ESP32硬件和固件 淘宝搜ESP32模块,20-50元都有,自带usb口,即插即用. 固件下载地址:MicroPython - Python for microcontrollers 2.烧录方法 为简化入门难度,建议此处先使用带GUI的开发工具THonny,记得不是给你理发的tony老师. 烧录的入口是: 后期通过脚本一次型生成和烧…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...