C 语言零基础入门教程(二十三)

news2024/11/18 16:20:09

C 可变参数

有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数。C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数。下面的实例演示了这种函数的定义。

int func(int, ... ) 
{
   .
   .
   .
}
 
int main()
{
   func(2, 2, 3);
   func(3, 2, 3, 4);
}

请注意,函数 func() 最后一个参数写成省略号,即三个点号(…),省略号之前的那个参数是 int,代表了要传递的可变参数的总数。为了使用这个功能,您需要使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏。具体步骤如下:
1、定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。
2、在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。
3、使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。
4、使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。
5、使用宏 va_end 来清理赋予 va_list 变量的内存。
现在让我们按照上面的步骤,来编写一个带有可变数量参数的函数,并返回它们的平均值:

#include <stdio.h>
#include <stdarg.h>
 
double average(int num,...)
{
 
    va_list valist;
    double sum = 0.0;
    int i;
 
    /* 为 num 个参数初始化 valist */
    va_start(valist, num);
 
    /* 访问所有赋给 valist 的参数 */
    for (i = 0; i < num; i++)
    {
       sum += va_arg(valist, int);
    }
    /* 清理为 valist 保留的内存 */
    va_end(valist);
 
    return sum/num;
}
 
int main()
{
   printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

当上面的代码被编译和执行时,它会产生下列结果。应该指出的是,函数 average() 被调用两次,每次第一个参数都是表示被传的可变参数的总数。省略号被用来传递可变数量的参数。

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000

C 内存管理

本章将讲解 C 中的动态内存管理。C 语言为内存的分配和管理提供了几个函数。这些函数可以在 <stdlib.h> 头文件中找到。
在这里插入图片描述
注意:void * 类型表示未确定类型的指针。C、C++ 规定 void * 类型可以通过类型转换强制转换为任何其它类型的指针。

动态分配内存

编程时,如果您预先知道数组的大小,那么定义数组时就比较容易。例如,一个存储人名的数组,它最多容纳 100 个字符,所以您可以定义数组,如下所示:

char name[100];

但是,如果您预先不知道需要存储的文本长度,例如您想存储有关一个主题的详细描述。在这里,我们需要定义一个指针,该指针指向未定义所需内存大小的字符,后续再根据需求来分配内存,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* 动态分配内存 */
   description = (char *)malloc( 200 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student in class 10th");
   }
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
}

当上面的代码被编译和执行时,它会产生下列结果:

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

上面的程序也可以使用 calloc() 来编写,只需要把 malloc 替换为 calloc 即可,如下所示:

calloc(200, sizeof(char));

当动态分配内存时,您有完全控制权,可以传递任何大小的值。而那些预先定义了大小的数组,一旦定义则无法改变大小。

重新调整内存的大小和释放内存

当程序退出时,操作系统会自动释放所有分配给程序的内存,但是,建议您在不需要内存时,都应该调用函数 free() 来释放内存。

或者,您可以通过调用函数 realloc() 来增加或减少已分配的内存块的大小。让我们使用 realloc() 和 free() 函数,再次查看上面的实例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* 动态分配内存 */
   description = (char *)malloc( 30 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student.");
   }
   /* 假设您想要存储更大的描述信息 */
   description = (char *) realloc( description, 100 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcat( description, "She is in class 10th");
   }
   
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
 
   /* 使用 free() 函数释放内存 */
   free(description);
}

当上面的代码被编译和执行时,它会产生下列结果:

Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th

您可以尝试一下不重新分配额外的内存,strcat() 函数会生成一个错误,因为存储 description 时可用的内存不足。

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

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

相关文章

Centos8中安装配置php

一、问题描述Centos8中我们在使用Apache部署配置网站的时候&#xff0c;发现Apache服务已经正常启动且网站也配置完成到Apache主目录中&#xff0c;但是访问时网站却不能正常运行【即&#xff1a;只能够以列表的方式列出所有网站的资源文件&#xff0c;而不是以网页的形式展现】…

关于荧光素76863-28-0,FITC-5-thiosemicarbazide,荧光素-5-氨基硫脲 相关知识分享

荧光素-5-氨基硫脲&#xff0c;Fluorescein-5-thiosemicarbazide&#xff0c;FITC-5-thiosemicarbazide荧光素-5-氨基硫脲是一种含胺的荧光探针&#xff0c;可用于标记糖和蛋白质羰基衍生物Product specifications&#xff1a;1.CAS No&#xff1a;76863-28-02.Molecular formu…

超越OCR的富文档内容解析神器LayoutParser

论文题目&#xff1a;《A unified toolkit for Deep Learning Based Document Image Analysis》 论文链接&#xff1a;https://arxiv.org/abs/2103.15348 论文官方网站&#xff1a;https://layout-parser.github.io/ 论文开源项目&#xff1a;https://github.com/Layout-Par…

Ubuntu 18.04安装配置MySQL数据库

文章目录1. 安装MySQL数据库2. 配置MySQL数据库3. 远程访问设置4. Navicat连接MySQL数据库1. 安装MySQL数据库 这里可以通过包管理工具apt安装MySQL数据库&#xff0c;在ubuntu18.04下mysql版本默认为5.7。 安装命令如下&#xff1a; sudo apt-get install mysql-server安装…

【Echarts雪花宝典特殊示例100+】 目录

目前已发表2篇示例文章vueecharts系列教程旨在为开发者提供简单快捷的代码示例&#xff0c;复制即可用。在每一个示例中&#xff0c;解释相应的API知识点&#xff0c;做到简易实现&#xff0c;轻松学会。 通常一个Echarts图表通常由title(标题)、legend(图例)、grid&#xff0…

ESP-IDF:插入排序和希尔排序测试

代码&#xff1a; /插入排序和希尔排序测试/ void printArray14(int arr[], int len) { for (int i 0; i < len; i) { cout << arr[i] << " "; } cout << endl; } void insertSort(int arr[], int start, int end) { // 无序插入有序队列&am…

BM19 寻找峰值

目录 描述 示例1 思路&#xff1a; 代码&#xff1a; 描述 给定一个长度为n的数组nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可。 1.峰值元素是指其值严格大于左右相邻值的元素。严格…

专访三维空间雷成老师 | 原来水墨画风格的3D建筑动画可以如此惊艳……

CGarchitect 是业界赫赫有名的国际3D建筑赛事&#xff0c;2005年首次举办至今已成功举办了17届大赛&#xff0c;每年都吸引了全球许多知名的建筑设计工作室、动画工作室、艺术家及学生参赛。2021年的CGarchitect奖项类别包括图像组、影片组和交互组&#xff0c;其中图像组和影片…

【Rust】17. Rust 中的并发

17.1 线程 17.1.1 spawn&#xff1a;创建新线程 thread::spawn&#xff1a;创建一个新线程&#xff0c;需要传递一个闭包&#xff0c;并在其中包含希望在新线程运行的代码thread::sleep&#xff1a;调用强制线程停止执行一小段时间。比如&#xff1a;thread::sleep(Duration::…

深入理解MySql(一)MySql视图、存储过程、预处理语句、触发器、定时器

MySql视图、存储过程、预处理语句、触发器、定时器 1、视图 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 视图只保存了查询的…

iOS面试- 0x02 WebView

有了UIWebView&#xff0c;为什么还需要WKWebView&#xff1f; UIWebVieW的缺点&#xff1a; 笨重难用、内存泄露、内存消耗大&#xff0c;性能差 —— WKWebView提高性能 WKWebView 拥有60fps滚动刷新率和safari相同的js引擎等优势。 1、WKWebView 白屏问题 WKWebView是一个多…

ElasticSearch6.x版本的Scroll滚动查询讲解及Kibana和SpringBoot实操演示

文章目录一、Scroll滚动查询介绍二、Kibana上操作三、SpringBoot中操作四、总结一、Scroll滚动查询介绍 ElasticSearch中在进行普通的查询时&#xff0c;默认只会查询出来10条数据。我们通过设置ElasticSearch中的size可以将最终的查询结果从10增加到10000。但这时候如果我们需…

Sensor曝光和帧率基础知识

Sensor曝光和帧率基础知识1. 简介2. H_BLANK和V_BLANK3. 曝光原理3.1 Sensor逐行曝光基本原理3.2 Sensor全局曝光基本原理4. 曝光时间计算公式4.1 曝光一行的时间line_timeline\_timeline_time4.2 曝光一帧的时间exposure_timeexposure\_timeexposure_time4.3 帧率(fps)的计算1…

2023,“蔚小理”真的经不起更多“事故”了

历史总是惊人的相似。2013年&#xff0c;哈弗品牌独立出来&#xff0c;与长城品牌并行运营&#xff0c;当时推出两年的哈弗H6正卖得火热&#xff0c;推动SUV这个细分品类在中国快速成长&#xff0c;中国自主品牌也借SUV开始攻占被合资品牌占领的市场。时移势易。十年后的2023年…

浅析TSINGSEE车载监控平台助力城市公交智能监管的方案设计

道路运输已成为铁路以外最重要的地面运输方式&#xff0c;在国民经济和社会发展中发挥着举足轻重的作用。然而&#xff0c;随着汽车的普及和交通需求的快速增长&#xff0c;道路运输带来的交通拥堵、交通事故和环境污染等负面影响日益突出&#xff0c;逐渐成为全球经济社会发展…

Baklib支招 ——如何帮助企业创建内部维基(wiki)?

企业维基&#xff08;wiki&#xff09;的重要的好处就是&#xff1a;可以按照个性化的理解和需求进行编辑&#xff0c;而不担心被别人修改。这个个人维基可以作为自己的外挂大脑使用&#xff0c;但是不要成为一个垃圾筐&#xff0c;什么都往里装&#xff0c;扔进去就再也不看了…

计算机SCI论文重复率需要控制在多少? - 易智编译EaseEditing

SCI论文的重复率一般在20%左右&#xff0c;一般是没有没问题的。 SCI期刊在检查论文重复率时&#xff0c;并不是简单的只看总重复率&#xff0c;还有单篇重复率。 目前有很多SCI期刊都会先查重&#xff0c;看重复率&#xff0c;但也会看内容。 而且&#xff0c;重复率高也不一定…

lio-sam学习笔记(一)

前言&#xff1a; 对于lio-sam框架的安装配置。 每一回不同框架的配置真是要了老命了。。。 一、安装依赖 官方github&#xff1a; GitHub - TixiaoShan/LIO-SAM: LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping lio-sam主要有两个依赖&am…

6.深度学习和计算

6.深度学习和计算 目录 层和块 自定义块顺序块在前向传播函数中执行代码 参数管理 参数访问 目标参数一次性访问所有参数从嵌套块收集参数 参数初始化 内置初始化自定义初始化 参数绑定 自定义层 不带参数的层带参数的层 读写文件 加载和保存张量加载和保存模型参数使用GPU 计…

JS中函数声明与函数表达式的区别

1、函数定义 JavaScript 中定义函数最常用的方式是函数声明和函数表达式。这两种技术非常相似&#xff0c;有时甚至难以区分&#xff0c;它们之间还是存在着微妙的差别。 JavaScript 定义函数的最基本方式是函数声明&#xff1a; 函数声明必须独立&#xff0c;但也能够被包含在…