[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.rhkb.cn/news/8487.html

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

相关文章

Canny 边缘检测

步骤 1.降噪 应用高斯滤波器&#xff0c;以平滑图像&#xff0c;滤除噪声。 边缘检测易受噪声影响&#xff0c;所以使用高斯滤波器平滑图像&#xff0c;降低噪声。 2.梯度 计算图像中每个像素点的梯度大小和方向。 计算大小 Sobel算子是一种常用的边缘检测滤波器&#xff…

【数据结构】_链表经典算法OJ:合并两个有序数组

目录 1. 题目描述及链接 2. 解题思路 3. 程序 3.1 第一版 3.2 第二版 1. 题目描述及链接 题目链接&#xff1a;21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。 新链表是通过拼接给…

LiteFlow Spring boot使用方式

文章目录 概述LiteFlow框架的优势规则调用逻辑规则组件定义组件内数据获取通过 DefaultContext自定义上下文 通过 组件规则定义数据通过预先传入数据 liteflow 使用 概述 在每个公司的系统中&#xff0c;总有一些拥有复杂业务逻辑的系统&#xff0c;这些系统承载着核心业务逻…

六、深入了解DI

依赖注入是⼀个过程&#xff0c;是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源&#xff0c;⽽资源指的就是对象. 在上⾯程序案例中&#xff0c;我们使⽤了 Autowired 这个注解&#xff0c;完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中。 关于依赖注…

c++贪心

本篇文章&#xff0c;我将同大家一起学习c的贪心&#xff01;&#xff01;&#xff01; 目录 第一题 题目链接 题目解析 代码原理 代码编写 第二题 题目链接 题目解析 代码原理 代码编写 第三题 题目链接 题目解析 代码原理 代码编写 第四题 题目链接 题目解…

高低频混合组网系统中基于地理位置信息的信道测量算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

【Python实现机器遗忘算法】复现2020年顶会CVPR算法Selective Forgetting

【Python实现机器遗忘算法】复现2020年顶会CVPR算法Selective Forgetting 1 算法原理 Golatkar, A., Achille, A., & Soatto, S. (2020). Eternal sunshine of the spotless net: Selective forgetting in deep networks. In Proceedings of the IEEE/CVF Conference on Co…

Linux(NTP配置)

后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; NTP环境搭建 服务端客户端192.168.111.10192.168.111.11Linux MySQL5.7 3.10.0-1160.el7.x86_…

神经网络|(四)概率论基础知识-古典概型

【1】引言 前序学习了线性回归的基础知识&#xff0c;了解到最小二乘法可以做线性回归分析&#xff0c;但为何最小二乘法如此准确&#xff0c;这需要从概率论的角度给出依据。 因此从本文起&#xff0c;需要花一段时间来回顾概率论的基础知识。 【2】古典概型 古典概型是我…

21款炫酷烟花合集

系列专栏 《Python趣味编程》《C/C趣味编程》《HTML趣味编程》《Java趣味编程》 写在前面 Python、C/C、HTML、Java等4种语言实现18款炫酷烟花的代码。 Python Python烟花① 完整代码&#xff1a;Python动漫烟花&#xff08;完整代码&#xff09; ​ Python烟花② 完整…

新项目上传gitlab

Git global setup git config --global user.name “FUFANGYU” git config --global user.email “fyfucnic.cn” Create a new repository git clone gitgit.dev.arp.cn:casDs/sawrd.git cd sawrd touch README.md git add README.md git commit -m “add README” git push…

Brightness Controller-源码记录

Brightness Controller 亮度控制 一、概述二、ddcutil 与 xrandr1. ddcutil2. xrandr 三、部分代码解析1. icons2. ui3. utilinit.py 一、概述 项目&#xff1a;https://github.com/SunStorm2018/Brightness.git 原理&#xff1a;Brightness Controlle 是我在 Ubuntu 发现上调…

机器学习-K近邻算法

文章目录 一. 数据集介绍Iris plants dataset 二. 代码三. k值的选择 一. 数据集介绍 鸢尾花数据集 鸢尾花Iris Dataset数据集是机器学习领域经典数据集&#xff0c;鸢尾花数据集包含了150条鸢尾花信息&#xff0c;每50条取自三个鸢尾花中之一&#xff1a;Versicolour、Setosa…

Day27-【13003】短文,线性表两种基本实现方式空间效率、时间效率比较?兼顾优点的静态链表是什么?如何融入空闲单元链表来解决问题?

文章目录 本次内容总览第四节&#xff0c;两种基本实现方式概览两种基本实现方式的比较元素个数n大于多少时&#xff0c;使用顺序表存储的空间效率才会更高&#xff1f;时间效率比较&#xff1f;*、访问操作&#xff0c;也就是读运算&#xff0c;读操作1、插入&#xff0c;2、删…

JavaSE第十一天——集合框架Collection

一、List接口 List接口是一个有序的集合&#xff0c;允许元素有重复&#xff0c;它继承了Collection接口&#xff0c;提供了许多额外的功能&#xff0c;比如基于索引的插入、删除和访问元素等。 常见的List接口的实现类有ArrayList、LinkedList和Vector。 List接口的实现类 …

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

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

kaggle社区LLM Classification Finetuning

之前有个一样的比赛&#xff0c;没去参加&#xff0c;现在弄了一个无限期的比赛出来 训练代码链接&#xff1a;fine_tune | Kaggle 推理代码链接&#xff1a;https://www.kaggle.com/code/linheshen/inference-llama-3-8b?scriptVersionId219332972 包链接&#xff1a;pack…

【Python实现机器遗忘算法】复现2021年顶会 AAAI算法Amnesiac Unlearning

【Python实现机器遗忘算法】复现2021年顶会 AAAI算法Amnesiac Unlearning 1 算法原理 论文&#xff1a;Graves, L., Nagisetty, V., & Ganesh, V. (2021). Amnesiac machine learning. In Proceedings of the AAAI Conference on Artificial Intelligence, volume 35, 115…

51单片机开发:点阵屏显示数字

实验目标&#xff1a;在8x8的点阵屏上显示数字0。 点阵屏的原理图如下图所示&#xff0c;点阵屏的列接在P0端口&#xff0c;行接在74HC595扩展的DP端口上。 扩展口的使用详见&#xff1a;51单片机开发&#xff1a;IO扩展(串转并)实验-CSDN博客 要让点阵屏显示数字&#xff0…

买卖股票的最佳时机 II

hello 大家好&#xff01;今天开写一个新章节&#xff0c;每一天一道算法题。让我们一起来学习算法思维吧&#xff01; 问题分析 本题要求计算在可以多次买卖股票&#xff08;但任何时候最多只能持有一股股票&#xff0c;也可以在同一天买卖&#xff09;的情况下能获得的最大…