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

《C缺陷和陷阱》-笔记(5)

目录

一、整数溢出

溢出

如何防止溢出

二、为函数main提供返回值           

连接

一、什么是连接器

连接器工作原理

三、声明与定义

四、命名冲突与static 修饰符

statia


一、整数溢出

溢出

C语言中存在两类整数算术运算,有符号运算与无符号运算。

在无符号算术运算中,没有所谓的“溢出”一说。所有的无符号运算都是以2的n次方为模,这里n是结果中的位数。

当两个操作数都是有符号整数时,“溢出”就有可能发生,而且“溢出”的结果是术定义的。

例如,假定a和b是两个非负整型变量,我们需要检查atb是否会“溢出”种想当然的方式是这样:

if (a + b < 0)
      complain();

这并不能正常运行。当a+b确实发生“溢出”时,所有关于结果如何的假设都不再可靠。

如何防止溢出

1.一种正确的方式是将a和b都强制转换为无符号整数:

if ((unsigned) a + (unsigned) b > INT _MAX)
complain()

此处的INT_MAX是一个已定义常量,代表可能的最大整数值。

2.不需要用到无符号算术运算的另一种可行方法是:
if (a > INT_ MAX - b)
complain();

二、为函数main提供返回值           

最简单的C程序也许是像下面这样:
main()
(
}

这个程序包含一个不易察觉的错误。函数main与其他任何函数一样,如果并未显式声明返回类型,那么函数返回类型就默认为是整型。但是这个程序中并没有给出任何返回值。
通常说来,这不会造成什么危害。         

然而,在某些情形下函数main的返回值却并非无关紧要。大多数C语言实现都通过函数main的返回值来告知操作系统该函数的执行是成功还是失败。

严格说来,我们前面的最简单的C程序应该像下面这样编写代码:
main()
{

return ;
}


或者写成:
main()
{
exit(0);
}

最为经典的“hello world ”程序看上去应该像这样:
# include < stdio.h>
main()
printf( " hello worla\n");
return 0;

}

连接

一个C程序可能是由多个分别编译的部分组成,这些不同部分通过一个通常叫做连接器(也叫连接编辑器,或载入器)的程序合并成一个整体。

在本章中,我们将考查一个典型的连接器,注意它是如何对C程序进行处理的,从而归纳出一些由于连接器的特点而可能导致的错误。

一、什么是连接器

C语言中的一个重要思想就是分别编译,即若干个源程序可以在不同的时候单独进行编译,然后在恰当的时候整合到一起。

编译器的责任是把C源程序“翻译”成对连接器有意义的形式,这样连接器就能够“读懂”C源程序了。

典型的连接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体,该实体能够被操作系统直接执行。

其中,某些目标模块是直接作为输入提供给连接器的;而另外一些目标模块则是根据连接过程的需要,从包括有类似printf 函数的库文件中取得的。


连接器通常把目标模块看成是由一组外部对象组成的。每个外部对象代表着机器内存中的某个部分,并通过一个外部名称来识别。

连接器工作原理

1.连接器的输入是一组目标模块和库文件。

2.连接器的输出是一个载入模块。

3.连接器读入目标模块和库文件,同时生成载入模块。

4.对每个目标模块中的每个外部对象,连接器都要检查载入模块,看是否已有同名的外部对象。

5.如果没有,连接器就将该外部对象添加到载入模块中;如果有,连接器就要开始处理命名冲突。

三、声明与定义

下面的声明语句:
int  a;


如果其位置出现在所有的函数体之外,那么它就被称为外部对象a的定义。因为外部对象a并没有被明确指定任何初始值,所以它的初始值默认为0。

下面的声明语句
int a a7;


在定义a的同时也为a明确指定了初始值。这个语句不仅为a分配内存,而且也说明了在该内存中应该存储的值。
下面的声明语句
extern int a;


并不是对a的定义。这个语句仍然说明了a是一个外部整型变量,但是因为它包括了extern 关键字,这就显式地说明了a的存储空间是在程序的其他地方分配的。

每个外部对象都必须在程序某个地方进行定义。因此,如果一个程序中包括了语句
extern Int a:


那么,这个程序就必须在别的某个地方包括语句
int a;


这两个语句既可以是在同一个源文件中,也可以位于程序的不同源文件之中。

一个程序对同一个外部变量的定义不止一次,又将如何处理呢?也就是说,假定下面的语句
int a;


出现在两个或者更多的不同源文件中,情况会是怎样呢?如果
int a = 7;


出现在一个源文件中,而语句
int a = 9;


出现在另一个源文件中,将出现什么样的情形呢?这个问题的答案与系统有关,不同的系统可能有不同的处理方式。严格的规则是,每个外部变量只能够定义一次。

如果外部变量的多个定义各指定一个初始值,例如:
int a = 7; 


出现在一个源文件中,而
int a  = 9;


出现在另一个源文件中,大多数系统都会拒绝接受该程序。

要想在所有的C语言实现中避免这个问题,解决办法就是每个外部变量只定义一次。

四、命名冲突与static 修饰符

两个具有相同名称的外部对象实际上代表的是同一个对象,即使本意并非如此,但系统却会如此处理。因此,如果在两个不同的源文件中都包括了定义
int a;


那么,它或者表示程序错误(如果连接器禁止外部变量重复定义的话),或者在两个源文件中共享a的同一个实例(无论两个源文件中的外部变量a是否应该共享)。

即使其中a的一个定义是出现在系统提供的库文件中,也仍然进行同样的处理

statia

static 修饰符是一个能够减少此类命statia名冲突的有用工具。例如,以下声明语句
statia int a;
其含义与下面的语句相同
int  a
只不过,a的作用域限制在一个源文件内,对于其他源文件,a是不可见的。

因此,如果若干个函数需要共享一组外部对象,可以将这些函数放到一个源文件中,把它们需要用到的对象也都在同一个源文件中以static 修饰符声明。


static 修饰符不仅适用于变量,也适用于函数。如果函数f需要调用另一个函数g,而且只有函数f需要调用函数g,我们可以把函数f与函数g都放到同一个源文件中,并且声明函数g为static :

static  int ;
q( int x)

{

         /*g函数体*/

}

void f(){

{

            /*其他内容*/
  b = g(a); 
}
我们可以在多个源文件中定义同名的函数g,只要所有的函数g都被定义为static ,或者仅仅只有其中一个函数g不是static 。因此,为了避免可能出现的命名冲突,如果一个函数仅仅被同一个源文件中的其他函数调用,我们就应该声明该函数为static 。

相关文章:

《C缺陷和陷阱》-笔记(5)

目录 一、整数溢出 溢出 如何防止溢出 二、为函数main提供返回值 连接 一、什么是连接器 连接器工作原理 三、声明与定义 四、命名冲突与static 修饰符 statia 一、整数溢出 溢出 C语言中存在两类整数算术运算&#xff0c;有符号运算与无符号运算。 在无…...

【数字图像处理matlab系列】保存图像

【数字图像处理系列】保存图像imwrite函数 使用函数imwrite可以将图像保存到本地上,该函数的语法为 imwrite(image_data, filename)其中,image_data是要写入的图像数据,可以是一个矩阵或一个三维数组(对于彩色图像),filename是要写入的文件名,可以包含路径信息。例如,…...

八股文三(Spring、Spring Cloud Alibaba)

Spring篇 什么是Spring Spring是个轻量级的框架&#xff0c;他有两大内核分别是IOC、AOPIOC是什么 * 依赖注入和控制反转&#xff0c;它是一种思想&#xff0c;创建对象不是直接new出来&#xff0c;而是交给IOC容器&#xff0c;由容器去创建进行管理&#xff0c;这就是控制反…...

一文带你详解天池工业数据集

人工智能是国家战略性新兴产业&#xff0c;制造业是国民经济的主体&#xff0c;随着人口红利的消失&#xff0c;加强设备自动化改造&#xff0c;提高生产自动化程度&#xff0c;减小劳动强度&#xff0c;改善作业环境&#xff0c;已经成为制造业的普遍共识。天池大赛开放出一批…...

08 龙芯平台openstack部署搭建-neutron-controller部署

一、创建neutron相关数据库、服务凭证和API端点 1.创建neutron数据库&#xff0c;授予合适的访问权限 mysql -uroot -ploongson -e “CREATE DATABASE neutron;” mysql -uroot -ploongson -e “GRANT ALL PRIVILEGES ON neutron.* TO ‘neutron’‘localhost’ IDENTIFIED B…...

JAVA 100道题(6)

6.创建一个表示矩形的类&#xff0c;包括宽度和高度属性&#xff0c;以及计算面积和周长的方法。 下面是一个简单的Python类&#xff0c;表示矩形&#xff0c;包含宽度和高度属性&#xff0c;以及计算面积和周长的方法&#xff1a; python复制代码 class Rectangle: def __ini…...

Leetcode面试经典150题

数组字符串 合并两个有序数组 思路 类似于归并排序&#xff0c;对两个有序数组进行合并即可&#xff0c;但是空间复杂度是O(nm); 代码 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int[] ans new int[n m];int i 0, j 0;int cnt 0;…...

王者荣耀使用的UDP通信,十几年编程没用过的协议

缘起 最近在查阅moba相关的资料时&#xff0c;看到了一篇王者荣耀的研发同学的技术分享&#xff0c;从文章中了解到王者荣耀的通信方式是UDP通信&#xff0c;回想到整个职业生涯&#xff0c;貌似并没有用过&#xff0c;今天特地整理下。 udp技术细节 udp协议 UDP协议叫做用…...

HiveQL详解

文章目录 前言一、数据定义语言&#xff08;DDL&#xff09;1. 数据库操作1.1 创建数据库1.2 删除数据库1.3 更改数据库1.4 使用数据库 2. 连接器操作2.1 创建连接器2.2 删除连接器2.3 修改连接器 3. 表操作3.1 创建表3.1.1 内部表与外部表3.1.1.1 内部表3.1.1.2 外部表3.1.1.3…...

Linux/Bizness

Enumeration nmap 用 nmap 扫描了常见的端口&#xff0c;发现对外开放了22,80,443 ┌──(kali㉿kali)-[~] └─$ nmap 10.10.11.252 Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-08 01:21 EST Nmap scan report for 10.10.11.252 Host is up (0.36s latency). Not…...

mysql 数据库 增删改查 基本操作

目录 一 SQL 详细介绍 &#xff08;一&#xff09;SQL 分类 &#xff08;二&#xff09; SQL 语言规范 &#xff08;三&#xff09;数据库对象和命名 1&#xff0c;数据库的组件(对象)&#xff1a; 2&#xff0c;命名规则&#xff1a; &#xff08;四&#xff09; SQL…...

计算机网络——物理层(编码与调制)

计算机网络——编码与调制 基带信号和宽带信号编码与调制数字数据编码为数字信号非归零编码归零编码反向不归零编码曼彻斯特编码差分曼彻斯特编码4B/5B编码 数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号 我们之前讲了物理层的一些基础知识和两个准则&a…...

PHP魔术方法详解

__construct() 构造函数用于初始化新创建的对象。PHP 5 之后不推荐使用类名作为构造函数。 class Person {public $name;public $age;public function __construct($name, $age) {$this->name $name;$this->age $age;} }$person new Person("Alice", 30);…...

游戏 AI 反作弊|内附解决方案详情!

我们提出使用在游戏中广泛存在的回放日志数据&#xff0c;重构出玩家当局的表现。在回放 日志数据中&#xff0c;我们构建了玩家的时序行为数据&#xff0c;并基于该时序行为数据&#xff0c;分别搭建 了透视和自瞄外挂检测系统&#xff0c;该方法和系统可广泛应用于各种在线…...

elementUI组件库样式修改整理

一、整体修改样式注意点 避免!important&#xff0c;能使用深度选择器就用深度选择器主题色使用变量&#xff0c;方便后期统一修改&#xff0c;最好新建一个单独的文件&#xff0c;专门用于定义公共变量样式文件尽量放在一个文件里&#xff0c;方便后期维护 二、单独element …...

还是了解下吧,大语言模型调研汇总

大语言模型调研汇总 一. Basic Language ModelT5GPT-3LaMDAJurassic-1MT-NLGGopherChinchillaPaLMU-PaLMOPTLLaMABLOOMGLM-130BERNIE 3.0 Titan 二. Instruction-Finetuned Language ModelT0FLANFlan-LMBLOOMZ & mT0GPT-3.5ChatGPTGPT-4AlpacaChatGLMERNIE BotBard 自从Cha…...

Win11初始化系统遇一文解决

这个是目录 一、设置内的初始化无法使用时&#xff0c;使用以下工具二、将桌面移动到D盘三、解决win11桌面右键创建只有一个带盾牌的文件夹问题四、win11 系统停止更新五、office安装1、使用的是 Office Tool plus2、使用WPS 六、D盘有感叹号七、打开组策略编辑器(gpedit.msc)失…...

vr虚拟现实游戏世界介绍|数字文化展览|VR元宇宙文旅

虚拟现实&#xff08;VR&#xff09;游戏世界是一种通过虚拟现实技术创建的沉浸式游戏体验&#xff0c;玩家可以穿上VR头显&#xff0c;仿佛置身于游戏中的虚拟世界中。这种技术让玩家能够全方位、身临其境地体验游戏&#xff0c;与游戏中的环境、角色和物体互动。 在虚拟现实游…...

kotlin 程序 编译与执行

准备kotlin环境 Ubuntu安装kotlin 1. 创建一个名为 hello.kt 文件&#xff0c;代码如下&#xff1a; fun main(args: Array<String>) {println("Hello, World!") }2. 使用 Kotlin 编译器编译应用 kotlinc hello.kt -include-runtime -d hello.jar-d: 用来设…...

Python学习:注释和运算符

python 注释 在Python中&#xff0c;注释用于在代码中添加解释、说明或者提醒&#xff0c;但并不会被解释器执行。Python中的注释以#开头&#xff0c;直到行末为止。下面是关于Python注释的详细解释和举例&#xff1a; 单行注释&#xff1a;使用#符号在行的开头添加注释&…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...