[c语言日寄]assert函数功能详解

在这里插入图片描述

【作者主页】siy2333
【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是进阶开发者,这里都能满足你的需求!
【食用方法】1.根据题目自行尝试 2.查看基础思路完善题解 3.学习拓展算法
【Gitee链接】资源保存在我的Gitee仓库:https://gitee.com/siy2333/study


文章目录

  • 前言
  • 一、assert 函数简介
    • assert 函数的定义
    • assert 函数的语法
    • assert 函数的功能
    • assert 函数的禁用
  • 二、assert 函数的使用场景
    • 验证函数参数
    • 验证函数返回值
    • 验证程序状态
    • 验证指针是否为空
    • 验证数组索引是否越界
    • 验证文件操作是否成功
    • 验证动态内存分配是否成功
  • 三、在发布(Release)版本中进行断言
    • 使用断言替代品
    • 使用日志记录
  • 四、assert 函数的注意事项
  • 总结


前言

在C语言的开发过程中,assert 函数是一个非常重要的调试工具。它可以帮助开发者在开发阶段快速发现和修复程序中的逻辑错误。本文将详细介绍 assert 函数的功能、使用方法。


一、assert 函数简介

assert 函数的定义

assert 函数是一个宏,定义在 <assert.h> 头文件中。它的主要作用是在程序运行时检查某个条件是否为真。如果条件为假(即表达式的值为0),程序将终止,并输出一条错误信息,指出断言失败的位置。

assert 函数的语法

#include <assert.h>
void assert(int expression);

expression:一个整型表达式,通常是一个条件判断。

assert 函数的功能

如果 expression 的值为非0(即条件为真),程序继续执行。如果 expression 的值为0(即条件为假),程序终止,并输出一条错误信息,指出断言失败的位置。

#include <stdio.h>
#include <assert.h>int main() {int a = 10;int b = 0;// 断言b不为0,避免除以0的错误assert(b != 0);int result = a / b;printf("Result: %d\n", result);return 0;
}

如果 b 的值为0,程序将输出类似以下的错误信息并终止:
a.exe: main.c:10: main: Assertion `b != 0’ failed.
Aborted (core dumped)

assert 函数的禁用

在 VS2022 中,可以通过定义 NDEBUG 宏来禁用 assert 函数,以提高程序的性能。

#define NDEBUG
#include <assert.h>int main() {int a = 10;int b = 0;// 断言b不为0,避免除以0的错误assert(b != 0);int result = a / b;printf("Result: %d\n", result);return 0;
}

当定义了 NDEBUG 宏时,assert 宏将被定义为空操作,不会对程序的性能产生影响。

二、assert 函数的使用场景

验证函数参数

在函数的开头,使用 assert 来验证传入的参数是否符合预期。这有助于在早期发现错误,避免在函数内部使用无效的参数。

#include <stdio.h>
#include <assert.h>void divide(int numerator, int denominator) {assert(denominator != 0); // 确保分母不为0printf("Result: %d\n", numerator / denominator);
}int main() {divide(10, 2); // 正常情况divide(10, 0); // 断言失败,程序终止return 0;
}

验证函数返回值

在调用函数后,使用 assert 来验证函数的返回值是否符合预期。这有助于确保函数的行为正确无误。

#include <stdio.h>
#include <assert.h>int add(int a, int b) {return a + b;
}int main() {int result = add(2, 3);assert(result == 5); // 确保返回值正确printf("Result: %d\n", result);return 0;
}

验证程序状态

在程序的关键位置,使用 assert 来验证程序的状态是否符合预期。这有助于发现程序中的逻辑错误。

#include <stdio.h>
#include <assert.h>int main() {int a = 10;int b = 20;int c = a + b;assert(c == 30); // 确保计算结果正确printf("c: %d\n", c);return 0;
}

验证指针是否为空

在使用指针之前,使用 assert 来验证指针是否为空。这有助于避免空指针解引用导致的程序崩溃。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>void print_array(int* arr, int size) {assert(arr != NULL); // 确保指针不为空for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int* arr = (int*)malloc(5 * sizeof(int));assert(arr != NULL); // 确保分配内存成功for (int i = 0; i < 5; i++) {arr[i] = i + 1;}print_array(arr, 5);free(arr);return 0;
}

验证数组索引是否越界

在访问数组元素时,使用 assert 来验证索引是否越界。这有助于避免数组越界访问导致的未定义行为。

#include <stdio.h>
#include <assert.h>void print_element(int* arr, int size, int index) {assert(index >= 0 && index < size); // 确保索引在有效范围内printf("Element at index %d: %d\n", index, arr[index]);
}int main() {int arr[] = {1, 2, 3, 4, 5};int size = sizeof(arr) / sizeof(arr[0]);print_element(arr, size, 2); // 正常情况print_element(arr, size, 5); // 断言失败,程序终止return 0;
}

验证文件操作是否成功

在进行文件操作时,使用 assert 来验证文件操作是否成功。这有助于避免文件操作失败导致的程序错误。

#include <stdio.h>
#include <assert.h>void read_file(const char* filename) {FILE* file = fopen(filename, "r");assert(file != NULL); // 确保文件打开成功// 读取文件内容fclose(file);
}int main() {read_file("example.txt");return 0;
}

验证动态内存分配是否成功

在使用 malloc、calloc 或 realloc 分配内存时,使用 assert 来验证内存分配是否成功。这有助于避免内存分配失败导致的程序错误。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>int main() {int* arr = (int*)malloc(5 * sizeof(int));assert(arr != NULL); // 确保内存分配成功for (int i = 0; i < 5; i++) {arr[i] = i + 1;}for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}printf("\n");free(arr);return 0;
}

三、在发布(Release)版本中进行断言

由于在发布版本中,assert被优化,不会对程序造成影响,此时需要其他的方法来进行判断。

使用断言替代品

在发布版本中,可以定义一个类似于 assert 的宏,但在断言失败时不会终止程序,而是给出错误提示或采取其他适当的措施。

#include <stdio.h>
#include <stdlib.h>#define RELEASE_ASSERT(condition, message) \if (!(condition)) { \printf("Assertion failed: %s\n", message); \exit(1); \}int main() {int a = 10;int b = 0;// 使用断言替代品RELEASE_ASSERT(b != 0, "b should not be zero");int result = a / b;printf("Result: %d\n", result);return 0;
}

使用日志记录

在发布版本中,可以将错误信息记录到日志文件中,以便后续分析和调试。

#include <stdio.h>
#include <stdlib.h>void log_error(const char* message) {FILE* log_file = fopen("error.log", "a");if (log_file) {fprintf(log_file, "Error: %s\n", message);fclose(log_file);}
}#define LOG_ASSERT(condition, message) \if (!(condition)) { \log_error(message); \printf("Assertion failed: %s\n", message); \exit(1); \}int main() {int a = 10;int b = 0;// 使用日志记录LOG_ASSERT(b != 0, "b should not be zero");int result = a / b;printf("Result: %d\n", result);return 0;
}

四、assert 函数的注意事项

  • 性能影响
    assert 函数在程序运行时会进行条件检查,因此会对程序的性能产生一定影响。在发布版本中,通常会通过定义 NDEBUG 宏来禁用 assert,以提高程序的性能。
  • 错误处理
    assert 函数在断言失败时会直接终止程序,不会进行任何错误处理。因此,在使用 assert 时,需要确保程序在断言失败时不会对系统造成严重的影响。如果需要进行更复杂的错误处理,可以使用其他错误处理机制,如返回错误代码或抛出异常 。
  • 条件表达式
    assert 函数的参数是一个整型表达式,因此需要确保表达式的值为0或非0。如果表达式的值为0,程序将终止;如果表达式的值为非0,程序将继续执行。

总结

assert 函数是C语言中一个非常重要的调试工具,可以帮助开发者在开发阶段快速发现和修复程序中的逻辑错误。
在 VS2022 中,assert 函数的实现和优化使得它在调试和开发过程中更加方便和高效。

关注窝,每三天至少更新一篇优质c语言题目详解~

[专栏链接QwQ] :⌈c语言日寄⌋CSDN
[关注博主ava]:siy2333
感谢观看~ 我们下次再见!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】_链表经典算法OJ:分割链表(力扣—中等)

目录 1. 题目描述及链接 2. 解题思路 2.1 思路1 2.2 思路2 2.3 思路3&#xff08;本题采取该解法&#xff09; 3. 题解程序 1. 题目描述及链接 题目链接&#xff1a;面试题 02.04. 分割链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个链表…

基于vue和elementui的简易课表

本文参考基于vue和elementui的课程表_vue实现类似课程表的周会议列表-CSDN博客&#xff0c;原程序在vue3.5.13版本下不能运行&#xff0c;修改两处&#xff1a; 1&#xff09;slot-cope改为v-slot 2&#xff09;return background-color:rgb(24 144 255 / 80%);color: #fff; …

【Unity3D】实现Decal贴花效果,模拟战旗游戏地形效果

目录 一、基础版 二、Post Process 辉光Bloom效果 矩形渐隐 涉及知识点&#xff1a;Decal贴花、屏幕后处理Bloom、屏幕空间构建世界空间、ChracterController物体移动、Terrain地形创建 一、基础版 Unity 2019.4.0f1 普通渲染管线&#xff08;非URP、非HDRP&#xff09; UR…

数据结构与算法学习笔记----求组合数

数据结构与算法学习笔记----求组合数 author: 明月清了个风 first publish time: 2025.1.27 ps⭐️一组求组合数的模版题&#xff0c;因为数据范围的不同要用不同的方法进行求解&#xff0c;涉及了很多之前的东西快速幂&#xff0c;逆元&#xff0c;质数&#xff0c;高精度等…

基于物联网设计的疫苗冷链物流监测系统

一、前言 1.1 项目开发背景 随着全球经济的发展和物流行业的不断创新&#xff0c;疫苗和生物制品的运输要求变得越来越高。尤其是疫苗的冷链物流&#xff0c;温度、湿度等环境因素的控制直接关系到疫苗的质量和效力&#xff0c;因此高效、可靠的冷链监控系统显得尤为重要。冷…

学习数据结构(1)时间复杂度

1.数据结构和算法 &#xff08;1&#xff09;数据结构是计算机存储、组织数据的方式&#xff0c;指相互之间存在⼀种或多种特定关系的数据元素的集合 &#xff08;2&#xff09;算法就是定义良好的计算过程&#xff0c;取一个或一组的值为输入&#xff0c;并产生出一个或一组…

基于RIP的MGRE实验

实验拓扑 实验要求 按照图示配置IP地址配置静态路由协议&#xff0c;搞通公网配置MGRE VPNNHRP的配置配置RIP路由协议来传递两端私网路由测试全网通 实验配置 1、配置IP地址 [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 15.0.0.1 24 [R1]int LoopBack 0 [R1-LoopBack0]i…

Oracle迁移DM数据库

Oracle迁移DM数据库 本文记录使用达梦官方数据迁移工具DTS&#xff0c;将Oracle数据库的数据迁移至达梦数据库。 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具&#xff0c;点击新建工程&#xff0c;填写好工程信息&#xff0c;如图&#xff1a; 2.2 新建迁…

微服务(一)

文章目录 项目地址一、微服务1.1 分析User的Domian Verb和Nouns 二、运行docker和k8s2.1 Docker1. 编写dockerfile2. 创建docker image3. 运行docker使用指定端口4. 查看当前运行的镜像5. 停止当前所有运行的docker6. 删除不用的docker images7. 将本地的image上传到hub里 2.2 …

分享|instructionfine-tuning 指令微调是提高LLM性能和泛化能力的通用方法

《生成式AI导论》课程中&#xff0c;李宏毅老师提到一篇关于“ instruction fine-tuning” 指令微调的论文&#xff1a; 《Scaling Instruction-Finetuned Language Models》 摘要分享&#xff1a; 事实证明&#xff0c; 在一组以指令形式表达的数据集上微调语言模型可以提…

python生成图片和pdf,快速

1、下载安装 pip install imgkit pip install pdfkit2、wkhtmltopdf工具包&#xff0c;下载安装 下载地址&#xff1a;https://wkhtmltopdf.org/downloads.html 3、生成图片 import imgkit path_wkimg rD:\app\wkhtmltopdf\bin\wkhtmltoimage.exe # 工具路径&#xff0c;安…

Hive:基本查询语法

和oracle一致的部分 和oracle不一样的部分 排序 oracle中,在升序排序中&#xff0c;NULL 值被视为最大的值&#xff1b;在降序排序中&#xff0c;NULL 值被视为最小的值。 在MySQL中&#xff0c;NULL 被视为小于任何非空值。 在Hive中, NULL是最小的; Hive除了可以用order…

Python GUI 开发 | PySide6 辅助工具简介

关注这个框架的其他相关笔记&#xff1a;Python GUI 开发 | PySide6 & PyQt6 学习手册-CSDN博客 在上一章中&#xff0c;我们介绍了如何搭建 PySide6 & PyQt6 的开发环境。在搭建环境的时候我们配置了几个几个快捷工具&#xff0c;很多小伙伴可能都不知道是干啥用的。那…

hive:数据导入,数据导出,加载数据到Hive,复制表结构

hive不建议用insert,因为Hive是建立在Hadoop之上的数据仓库工具&#xff0c;主要用于批处理和大数据分析&#xff0c;而不是为OLTP&#xff08;在线事务处理&#xff09;操作设计的。INSERT操作会非常慢 数据导入 命令行界面:建一个文件 查询数据>>复制>>粘贴到新…

HarmonyOS:ForEach:循环渲染

一、前言 ForEach接口基于数组类型数据来进行循环渲染&#xff0c;需要与容器组件配合使用&#xff0c;且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如&#xff0c;ListItem组件要求ForEach的父容器组件必须为List组件。 API参数说明见&#xff1a;ForEa…

基于PostgreSQL的自然语义解析电子病历编程实践与探索(上)

一、引言 1.1研究目标与内容 本研究旨在构建一个基于 PostgreSQL 的自然语义解析电子病历编程体系,实现从电子病历文本中提取结构化信息,并将其存储于 PostgreSQL 数据库中,以支持高效的查询和分析。具体研究内容包括: 电子病历的预处理与自然语言处理:对电子病历文本进…

安装 docker 详解

在平常的开发工作中&#xff0c;我们经常需要部署项目。随着 Docker 容器的出现&#xff0c;大大提高了部署效率。Docker 容器包含了应用程序运行所需的所有依赖&#xff0c;避免了换环境运行问题。可以在短时间内创建、启动和停止容器&#xff0c;大大提高了应用的部署速度&am…

深度学习项目--基于LSTM的糖尿病预测探究(pytorch实现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 LSTM模型一直是一个很经典的模型&#xff0c;一般用于序列数据预测&#xff0c;这个可以很好的挖掘数据上下文信息&#xff0c;本文将使用LSTM进行糖尿病…

初阶1 入门

本章重点 C的关键字命名空间C的输入输出缺省参数函数重载引用内联函数auto关键字基于范围的for循环指针的空值nullptr 1.C的关键字 c总共有63个关键字&#xff0c;其中包含c语言的32个 这些关键字不需要特意去记&#xff0c;在我们日后写代码的过程中会慢慢用到并记住。 2.…

动态规划DP 数字三角形模型(模型分析+例题分析+C++代码实现)(数字三角形、摘花生、最低通行费用、方格取数、传纸条)

总体概览 数字三角形 原题链接 AcWing 898.数字三角形 题目描述 给定一个如下图所示的数字三角形&#xff0c;从顶部出发&#xff0c;在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点&#xff0c;一直走到底层&#xff0c;要求找出一条路径&#xff0c;使路…