[大师C语言(第三篇)]C语言函数参数背后的秘密

C语言函数参数背后的秘密(一)

在C语言中,函数是执行特定任务的一段代码,可以通过参数传递数据。函数参数是C语言中非常基本且重要的概念,但它们背后的技术原理可能并不为人所熟知。本文将深入探讨C语言函数参数的技术细节,包括参数的传递方式、类型检查和参数的存储布局。

函数参数的传递方式

在C语言中,函数参数可以通过两种方式传递:值传递和地址传递。

值传递

值传递是指将参数的值复制到函数的形参中。在这种情况下,对形参的修改不会影响实参。

#include <stdio.h>void modify(int a) {a = 42;
}int main() {int x = 7;modify(x);printf("x = %d\n", x); // 输出 x = 7,x 的值没有被修改return 0;
}

在上述示例中,modify 函数接收 x 的值,并在函数内部将其修改为 42。但是,x 的原始值在 main 函数中保持不变。

地址传递

地址传递是指将参数的地址(指针)复制到函数的形参中。在这种情况下,对形参的修改将会影响实参。

#include <stdio.h>void modify_by_address(int *a) {*a = 42;
}int main() {int x = 7;modify_by_address(&x);printf("x = %d\n", x); // 输出 x = 42,x 的值被修改return 0;
}

在上述示例中,modify_by_address 函数接收 x 的地址,并在函数内部通过指针修改 x 的值为 42。这次,x 的原始值在 main 函数中被修改。

类型检查

在C语言中,函数参数的类型必须与形参声明的类型相匹配,或者能够隐式转换为形参的类型。如果类型不匹配,编译器将发出警告或错误。

#include <stdio.h>void print_int(int a) {printf("%d\n", a);
}int main() {char c = 'A';print_int(c); // 正确,char 可以隐式转换为 intreturn 0;
}

在上述示例中,print_int 函数期望接收一个 int 类型的参数,但是传递了一个 char 类型的参数。由于 char 可以隐式转换为 int,所以这是合法的。

函数参数的存储布局

在C语言中,函数参数在调用栈上按照从右到左的顺序依次压栈。这意味着最后一个参数首先被压入栈中,然后是倒数第二个参数,依此类推,直到第一个参数。

示例代码

以下代码展示了函数参数的存储布局:

#include <stdio.h>void print_args(int a, int b, int c) {printf("a = %d, b = %d, c = %d\n", a, b, c);
}int main() {int x = 1, y = 2, z = 3;print_args(z, y, x); // 输出 a = 3, b = 2, c = 1return 0;
}

在上述示例中,print_args 函数接收三个参数 zy 和 x。在调用 print_args(z, y, x) 时,z 首先被压入栈中,然后是 y,最后是 x。因此,在 print_args 函数内部,a 对应于 zb 对应于 yc 对应于 x

总结

在本文的第一部分中,我们探讨了C语言函数参数的传递方式、类型检查和参数的存储布局。这些是理解函数参数背后技术原理的基础知识。在下一部分中,我们将深入探讨函数参数的默认值、可变参数列表以及如何通过指针和数组传递多个参数。

C语言函数参数背后的秘密(二)

在第一部分中,我们讨论了C语言函数参数的基本传递方式、类型检查和存储布局。现在,让我们进一步探讨函数参数的高级特性,包括默认参数、可变参数列表,以及如何通过指针和数组传递多个参数。

默认参数

C语言不支持函数的默认参数,这意味着在函数定义中必须为所有参数提供默认值。然而,我们可以通过一些技巧来实现类似默认参数的效果。

使用宏定义

通过宏定义,我们可以为函数提供默认参数的假象。这种方法利用了宏的替换特性,允许在函数调用时省略某些参数。

#include <stdio.h>#define print_max(a, b) print_max_actual((a), (b))
void print_max_actual(int a, int b) {if (a > b) {printf("%d is maximum\n", a);} else {printf("%d is maximum\n", b);}
}int main() {int x = 10, y = 20;print_max(x, y); // 输出 20 is maximumprint_max(x);    // 编译错误,缺少参数return 0;
}

在上面的代码中,print_max 宏定义了一个带有两个参数的函数 print_max_actual。但是,这种方法有一个缺点:如果调用时省略了参数,编译器不会提供默认值,而是会产生错误。

使用函数重载

虽然C语言本身不支持函数重载,但我们可以通过编译器扩展(如GCC的函数属性)来实现类似的效果。

#include <stdio.h>void print_max(int a, int b, int c) {if (a > b && a > c) {printf("%d is maximum\n", a);} else if (b > c) {printf("%d is maximum\n", b);} else {printf("%d is maximum\n", c);}
}void print_max(int a, int b) {print_max(a, b, INT_MIN); // 使用最小整数值作为默认参数
}int main() {int x = 10, y = 20;print_max(x, y); // 输出 20 is maximumreturn 0;
}

在这个例子中,我们定义了两个 print_max 函数,一个带有两个参数,另一个带有三个参数。在两个参数的版本中,我们调用三个参数的版本,并将第三个参数设置为 INT_MIN,从而实现默认参数的效果。

可变参数列表

C语言提供了可变参数列表的功能,允许函数接受可变数量的参数。这通过 va_listva_startva_arg 和 va_end 等宏来实现。

示例代码

以下是一个使用可变参数列表的示例,该函数计算并打印给定数量的整数的平均值。

#include <stdio.h>
#include <stdarg.h>double average(int count, ...) {va_list args;double sum = 0.0;va_start(args, count);for (int i = 0; i < count; i++) {sum += va_arg(args, int);}va_end(args);return sum / count;
}int main() {double avg = average(4, 1, 2, 3, 4);printf("Average: %f\n", avg); // 输出 Average: 2.500000return 0;
}

在这个例子中,average 函数接受一个 int 类型的参数 count,表示后续可变参数的数量,然后通过 va_list 来访问这些参数。va_start 宏初始化 va_listva_arg 宏用于访问下一个参数,而 va_end 宏用于清理 va_list

通过指针和数组传递多个参数

在C语言中,可以通过指针和数组来传递多个参数。这种方法在处理大量数据时非常有用,因为它可以避免大量的参数传递。

示例代码

以下是一个使用指针和数组传递参数的示例,该函数计算一个整数数组的平均值。

#include <stdio.h>double average(int *array, int size) {double sum = 0.0;for (int i = 0; i < size; i++) {sum += array[i];}return sum / size;
}int main() {int numbers[4] = {1, 2, 3, 4};double avg = average(numbers, 4);printf("Average: %f\n", avg); // 输出 Average: 2.500000return 0;
}

在这个例子中,average 函数接受一个指向整数的指针 array 和整数 size,表示数组的大小。函数通过指针遍历数组,计算所有元素的和,然后除以数组的大小来得到平均值。

总结

在本文的第二部分中,我们探讨了C语言函数参数的高级特性,包括默认参数、可变参数列表,以及如何通过指针和数组传递多个参数。这些特性使得C语言函数更加灵活和强大,能够处理更加复杂和多样的数据结构。

了解函数参数背后的技术原理对于编写健壮和高效的C程序至关重要。通过深入理解这些概念,我们可以更好地利用C语言的强大功能,编写出更符合实际需求的代码。

总结

在第一部分中,我们深入探讨了C语言函数参数的基本传递方式、类型检查和存储布局。我们了解了函数参数可以通过值传递和地址传递两种方式传递,以及类型检查在C语言中的重要性。此外,我们还探讨了函数参数在调用栈上的存储布局,以及它们如何影响程序的执行。

值传递和地址传递

值传递是指将参数的值复制到函数的形参中,而地址传递是指将参数的地址(指针)复制到函数的形参中。这两种传递方式在C语言中都非常重要,它们决定了函数对实参的影响范围。

类型检查

类型检查是C语言中的一个关键特性,它确保了函数参数的类型与形参声明的类型相匹配。这有助于避免潜在的运行时错误,并确保程序的稳定性。

存储布局

在C语言中,函数参数在调用栈上按照从右到左的顺序依次压栈。这意味着最后一个参数首先被压入栈中,然后是倒数第二个参数,依此类推,直到第一个参数。了解函数参数的存储布局对于编写高效的C程序至关重要。

在第二部分中,我们进一步探讨了C语言函数参数的高级特性,包括默认参数、可变参数列表,以及如何通过指针和数组传递多个参数。我们了解了使用宏定义和函数重载实现默认参数的方法,以及可变参数列表在处理可变数量参数时的优势。此外,我们还探讨了通过指针和数组传递多个参数的方法,以及它们在处理大量数据时的灵活性。

默认参数

虽然C语言本身不支持函数的默认参数,但我们可以通过宏定义和函数重载来实现类似的效果。这使得C语言函数更加灵活和强大,能够处理更加复杂和多样的数据结构。

可变参数列表

C语言提供了可变参数列表的功能,允许函数接受可变数量的参数。这通过 va_listva_startva_arg 和 va_end 等宏来实现,使得函数能够处理任意数量的参数。

通过指针和数组传递多个参数

在C语言中,可以通过指针和数组来传递多个参数。这种方法在处理大量数据时非常有用,因为它可以避免大量的参数传递。通过指针和数组,我们可以轻松地传递和处理多个参数,从而提高程序的效率和可读性。

通过这两部分的探讨,我们现在对C语言函数参数背后的技术原理有了更深入的理解。从基本传递方式,到高级特性,每一步都是确保C程序能够正常运行的关键。了解这些细节对于编写健壮和高效的C程序至关重要。

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

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

相关文章

kkkkkkkkkkkk564

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 人工智能与机器学习 &#x1f4dd;人工智能相关概念☞什么是人工智能、机器学习、深度学习☞人工智能发…

YOLOv8 Tensorrt Python/C++部署详解

按照大佬的方法进行部署&#xff0c;但是中间出现了很多问题&#xff0c;这里进行一下总结。 YOLOv8 Tensorrt Python/C部署教程_yolo 安装tensorrt-CSDN博客https://blog.csdn.net/weixin_45747759/article/details/130341118 Monday-Leo/Yolov5_Tensorrt_Win10: A simple i…

Kafka从0到消费者开发

安装ZK Index of /zookeeper/zookeeper-3.9.2 下载安装包 一定要下载-bin的&#xff0c;不带bin的是源码&#xff0c;没有编译的&#xff0c;无法执行。-bin的才可以执行。 解压 tar -zxvf apache-zookeeper-3.9.2-bin.tar.gz 备份配置 cp zoo_sample.cfg zoo_sample.cfg-b…

物流集成商巨头-员工薪酬PK:今天国际、音飞存储,诺力股份

语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 以下内容为根据上市财报和公开数据整理&#xff0c;若有偏差&#xff0c;请联系小编修改。注意&#xff1a;各公司员…

ZYNQ实验--裸机程序固化

参考资料 正点原子《领航者 ZYNQ 之嵌入式 SDK 开发指南》详细的配置资料中都有介绍&#xff0c;本文只针对个人实验需求进行简要说明 固化流程 调试阶段是通过 JTAG 接口将 FPGA 配置文件和应用程序下载到 ZYNQ 器件中。但在实际应用中需要程序在上电或者复位时让程序自动运…

Adversarial Synthesis of Human Pose From Text # 论文阅读

URL https://arxiv.org/pdf/2005.00340 TD;DR 20 年 5 月来自高校的一篇论文&#xff0c;任务是用 GAN 生成 pose&#xff0c;目前 7 引用。 Model & Method 输入的是描述动作的 text&#xff0c;通过 text encoder&#xff08;本文用的是叫做 fastText 的方法&#…

迷宫中离入口最近的出口

题目链接 迷宫中离入口最近的出口 题目描述 注意点 maze[i][j] 要么是 ‘.’ &#xff0c;要么是 ‘’entrance.length 2entrance 一定是空格子出口的含义是 maze 边界上的空格子entrance格子不算出口 解答思路 广度优先遍历找到走i步时所能到达的所有节点位置&#xff0…

认识 Pixel 8a:这款 Google AI 手机拥有无与伦比的价值。

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

html+css-Day1(盒子模型)

一、常用属性 1、字体设置font "line-height" 是 CSS 中的一个属性&#xff0c;用于设置文本行之间的距离&#xff0c;也就是行间距。它影响着段落、行内元素或者任何包含文本的元素的可读性。"line-height" 可以设置为数字、长度单位&#xff08;如 px、e…

数据结构——希尔排序

基本思想&#xff1a; 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xff0c;取&#xff0c;重复上述…

【图文教程】PyCharm安装配置PyQt5+QtDesigner+PyUic+PyRcc

这里写目录标题 PyQt5、Qt Designer、PyUic、PyRcc简介&#xff08;1&#xff09;下载安装PyQt5&#xff08;2&#xff09;打开designer.exe所在位置&#xff08;3&#xff09;在PyCharm中配置QtDesigner&#xff08;4&#xff09;验证QtDesigner是否配置成功&#xff08;5&…

通过编写dockerfile部署python项目

docker命令总览 docker通过dockerfile构建镜像常用命令 # 创建镜像&#xff08;进入dockerfile所在的路径&#xff09; docker build -t my_image:1.0 .# 查看镜像 docker images# 创建容器 docker run -dit --restartalways -p 9700:9700 --name my_container my_image:1.0 #…

阿里发布通义千问2.5:一文带你读懂通义千问!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

就业班 第三阶段(zabbix) 2401--5.9 day1 普通集zabbix 5.0部署 nginx部署+agent部署

文章目录 环境一、zabbix 5.0 部署1、安装yum源2、安装相关软件3、数据库安装和配置mariaDB数据库mysql57数据库 安装mysql万能卸载mysql代码&#xff1a;启动mysql并初始化4、数据表导入5、修改配置&#xff0c;启动服务6、配置 web GUI7、浏览器访问注意数据加密的选项不要勾…

分享四种免费获取SSL的方式

SSL证书目前需要部署安装的网站很多&#xff0c;主要还是基于国内目前对证书的需求度在不断的升高&#xff0c;网站多了、服务器多了之后。网络安全问题就成为了大家不得不面对的一个重要的问题了。SSL证书的作用有很多&#xff0c;这里就不一一详述了&#xff0c;本期作品主要…

RSAC 2024现场:谷歌展望大模型在网络安全领域的前景

人类距离将网络安全的控制权交给生成式AI还有多远&#xff1f; 前情回顾RSAC2024动态 伪造内容鉴别厂商Reality Defender斩获2024 RSAC创新沙盒冠军 RSAC 2024上值得关注的10款网络安全产品 RSAC 2024创新沙盒十强出炉&#xff0c;谁能夺冠&#xff1f; 安全内参5月8日消息…

table表格 如何加卡片 实现?

实现非常简单 代码 const columnsinsu [{dataIndex: nowdate,key: nowdate,render: (text, record) ><Cardhoverablestyle{{width: 97%,height: 90,}}// cover{<img alt"example" src"https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png&…

浅析安全用电监控系统在工厂的研究与应用论述

摘 要&#xff1a;随着社会时代的发展&#xff0c;人们的安全意识越来越强烈&#xff0c;在人们生活和工作中离不开各种用电设备&#xff0c;用电设备的安全使用是保障人们生命安全的重要内容。工厂因自身厂内工作环境的特殊性&#xff0c;用电设备的种类多且复杂&#xff0c;如…

指针的奥秘(二):指针与数组的联系+字符指针+二级指针+指针数组+《剑指offer》笔试题

指针 一.指针与数组的联系1.数组名的理解2.使用指针访问数组3.一维数组传参的本质 二.字符指针1.字符指针隐藏秘密2.常量字符串3.《剑指offer》笔试题 三.二级指针四.指针数组1.指针数组模拟二维数组 一.指针与数组的联系 1.数组名的理解 也许大部分人认为数组名就是一个名称&…

TL-WN826N无线网卡连接电脑蓝屏,提示rtl8188gu.sys

TL-WN826N无线网卡插电脑就蓝屏&#xff0c;提示rtl8188gu.sys 处理方法&#xff1a; 设备管理器中卸载其他的2.0无线网卡程序和功能中卸载网卡驱动TPlink官网下载 TL-WN826N V1.0_1.0.0&#xff08;https://www.tp-link.com.cn/product_572.html?vdownload&#xff09;&…