[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…

kotlin内联函数——runCatching

1.runCatching作用 代替try{}catch{}异常处理&#xff0c;用于捕获异常。 2.runCatching函数介绍 参数&#xff1a;上下文引用对象为参数返回值&#xff1a;lamda表达式结果 调用runCatching函数&#xff0c;如果调用成功则返回其封装的结果&#xff0c;并可回调onSuccess函…

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

数据结构与算法学习笔记----求组合数 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;并产生出一个或一组…

数据库表数据导出攻略:SQL脚本生成全解析

摘要 为了将SQL Server中的特定数据库表及其数据导出为SQL脚本&#xff0c;用户可以遵循一系列明确的步骤。首先&#xff0c;在SQL Server Management Studio中启动目标数据库&#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…

获取加工视图下所有元素

UF_SETUP_ask_program_root //程序顺序 视图 UF_SETUP_ask_mct_root //机床视图 UF_SETUP_ask_mthd_root //加工方法视图 UF_SETUP_ask_geom_root //几何视图 UF_initialize();//初始化 UF_UI_ONT_refresh();//刷新加工导航器 UF_UI_open_listing_window(); tag_t …

C#实现SQL Server数据血缘关系生成程序

要在现有的C#程序中添加功能&#xff0c;输出SQL Server数据血缘关系的三张表到Excel文件&#xff0c;我们需要进行以下几个步骤&#xff1a; 分析存储过程、视图和函数中的引用关系&#xff0c;构建数据血缘关系。 按依赖性从小到大排序表的顺序。 找出对应生成表的数据的存储…

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 …

现代操作系统一点点

现代操作系统 操作系统为所有其他软件提供基础的运行环境。 操作系统包含很多用于控制输入/输出设备的驱动 文件也是抽象出来的 操作系统的一个主要任务是隐藏硬件&#xff0c;呈现给程序&#xff08;以及程序员&#xff09;良好、清晰、优雅、一致的抽象。 shell也是操作系统提…

分享|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;安…

菜鸟之路Day09一一集合进阶(二)

菜鸟之路Day09一一集合进阶(二) 作者&#xff1a;blue 时间&#xff1a;2025.1.27 文章目录 菜鸟之路Day09一一集合进阶(二)0.概述1.泛型1.1泛型概述1.2泛型类1.3泛型方法1.4泛型接口1.5泛型通配符 2.Set系列集合2.1遍历方式2.2HashSet2.3LinkedHashSet2.4TreeSet 0.概述 内…

Hive:基本查询语法

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

在RHEL 8.10上安装开源工业物联网解决方案Thingsboard 3.9

在RHEL/CentOS/Rocky/AlmaLinux/Oracle Linux 8单节点上安装 备注&#xff1a; 适用于单节点 是否支持欧拉&#xff1f;&#xff1f;&#xff1f; 前提条件 本指南描述了如何在RHEL/CentOS 7/8上安装ThingsBoard。硬件要求取决于所选的数据库和连接到系统的设备数量。要在单…