阐述 C 语言中的参数传递机制

C语言

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
📙C 语言百万年薪修炼课程 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。

分割线

文章目录

  • C 语言中的参数传递机制
  • 一、值传递
  • 二、指针传递
  • 三、数组作为参数传递
  • 四、结构体作为参数传递
  • 五、函数指针作为参数传递
  • 六、参数传递的选择策略
  • 七、常见错误和注意事项
    • (一)指针未初始化
    • (二)空指针解引用
    • (三)内存泄漏
    • (四)指针越界

分割线


C 语言中的参数传递机制

在 C 语言中,参数传递是函数之间进行数据交互的重要方式。C 语言主要采用了两种参数传递机制:值传递和指针传递。

分割线

一、值传递

值传递是指在函数调用时,将实际参数的值复制一份传递给函数的形式参数。在函数内部对形式参数的修改不会影响到实际参数的值。

#include <stdio.h>// 定义一个交换两个整数的函数(值传递方式)
void swap(int a, int b) {int temp = a;a = b;b = temp;
}int main() {int x = 5, y = 10;printf("交换前:x = %d, y = %d\n", x, y);swap(x, y);printf("交换后:x = %d, y = %d\n", x, y);return 0;
}

在上述示例中,swap 函数采用值传递方式接收参数 ab。在函数内部对 ab 的交换操作并不会影响到 main 函数中的 xy 的值。因为 ab 只是 xy 的副本。

值传递的优点在于简单直观,函数内部的操作不会意外修改外部的变量。但缺点是对于较大的数据结构(如结构体、数组等),复制整个数据结构可能会导致较大的性能开销。

分割线

二、指针传递

指针传递是指在函数调用时,将实际参数的地址(指针)传递给函数的形式参数。通过指针,函数可以直接操作实际参数所指向的内存空间,从而实现对实际参数的修改。

#include <stdio.h>// 定义一个通过指针交换两个整数的函数
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 5, y = 10;printf("交换前:x = %d, y = %d\n", x, y);swap(&x, &y);printf("交换后:x = %d, y = %d\n", x, y);return 0;
}

在这个示例中,swap 函数接收两个指针参数 *a*b。通过解引用指针来操作它们所指向的变量,从而实现了对 main 函数中 xy 的值的交换。

指针传递的优点是可以直接修改函数外部的变量,避免了值传递时复制大型数据结构的开销。但缺点是使用不当可能会导致内存访问错误,如空指针解引用、野指针等。

分割线

三、数组作为参数传递

在 C 语言中,当数组作为参数传递给函数时,实际上传递的是数组的首地址,也就是一种指针传递。

#include <stdio.h>// 计算数组元素之和的函数
int sum(int arr[], int size) {int total = 0;for (int i = 0; i < size; i++) {total += arr[i];}return total;
}int main() {int array[] = {1, 2, 3, 4, 5};int size = sizeof(array) / sizeof(array[0]);int result = sum(array, size);printf("数组元素之和为:%d\n", result);return 0;
}

sum 函数中,虽然形式参数写成了 int arr[],但实际上它等价于 int *arr。在函数内部通过指针遍历数组元素并计算总和。

分割线

四、结构体作为参数传递

结构体可以通过值传递和指针传递两种方式进行参数传递。

#include <stdio.h>// 定义一个结构体
struct Point {int x;int y;
};// 通过值传递结构体参数
void printPointValue(struct Point p) {printf("值传递:(x = %d, y = %d)\n", p.x, p.y);
}// 通过指针传递结构体参数
void printPointPointer(struct Point *p) {printf("指针传递:(x = %d, y = %d)\n", p->x, p->y);
}int main() {struct Point pt = {10, 20};printPointValue(pt);printPointPointer(&pt);return 0;
}

对于较小的结构体,值传递可能比较方便。但对于较大的结构体,为了避免复制的开销,通常使用指针传递。

分割线

五、函数指针作为参数传递

函数指针可以作为参数传递给函数,这使得函数具有更高的灵活性和可扩展性。

#include <stdio.h>// 定义一个函数类型
typedef int (*Operation)(int, int);// 执行指定操作的函数
int performOperation(int a, int b, Operation op) {return op(a, b);
}// 加法函数
int add(int a, int b) {return a + b;
}// 减法函数
int subtract(int a, int b) {return a - b;
}int main() {int x = 5, y = 3;int sum = performOperation(x, y, add);int difference = performOperation(x, y, subtract);printf("和:%d, 差:%d\n", sum, difference);return 0;
}

在上述示例中,performOperation 函数接受一个函数指针 op 作为参数,根据传递的不同函数指针执行不同的操作。

分割线

六、参数传递的选择策略

在实际编程中,选择值传递还是指针传递取决于多个因素:

  1. 如果函数不需要修改实际参数的值,并且实际参数的数据量较小,值传递通常是一个简单且安全的选择。
  2. 如果函数需要修改实际参数的值,或者实际参数是较大的数据结构(如大型数组、结构体等),指针传递更合适,以避免复制数据的开销。
  3. 对于需要频繁调用且参数较大的函数,指针传递可以提高性能。

分割线

七、常见错误和注意事项

(一)指针未初始化

int *ptr;
*ptr = 10;  // 错误:ptr 未初始化,指向的内存位置是不确定的

在使用指针之前,必须确保它被正确地初始化指向有效的内存地址。

(二)空指针解引用

int *ptr = NULL;
*ptr = 10;  // 错误:解引用空指针会导致运行时错误

在对指针进行解引用操作之前,要检查指针是否为空。

(三)内存泄漏

int *allocateMemory() {int *ptr = (int *)malloc(sizeof(int));return ptr;  // 没有释放内存,导致内存泄漏
}

当使用动态分配内存(如 malloccalloc 等)时,在不再使用所分配的内存时,必须使用 free 函数释放内存,以避免内存泄漏。

(四)指针越界

int array[5];
int *ptr = array;
for (int i = 0; i < 10; i++) {ptr[i] = i;  // 错误:指针越界访问
}

在通过指针访问数组或其他数据结构时,要确保不超出其边界。

理解 C 语言中的参数传递机制对于编写正确、高效的 C 程序至关重要。需要根据具体的需求和情况选择合适的参数传递方式,并注意避免常见的错误。


分割线

🎉相关推荐

  • 📙C 语言百万年薪修炼课程 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。
  • 🍅博客首页-关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📙CSDN专栏-C语言修炼
  • 📙技术社区-墨松科技

分割线



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

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

相关文章

多表查询sql

概述&#xff1a;项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系&#xff0c;分为三种&#xff1a; 一对多多对多一对一 一、多表关系 一对多 案例&#xff1a;部门与…

【PowerShell】-1-快速熟悉并使用PowerShell

目录 PowerShell是什么&#xff1f;和CMD的区别&#xff1f; PowerShell的演变 自动化IT管理任务 一些名词 详尽的PowerShell开始之路 1.打开PowerShell&#xff1a; 2.基本命令&#xff1a; &#xff08;1&#xff09;Get-Process &#xff08;2&#xff09;变量赋值…

【核心笔记】Java入门到起飞,小白都能看懂的Java教程 (五)——数组

一 数组的定义和初始化 定义数组 数据类型[] 数组名&#xff1b;例 int[] arr; 数据类型 数组名[]&#xff1b;例 int arr[]; 数组初始化 数据类型[] 数组名 new 数据类型[] {值}&#xff1b;例 int[] arr new int[] {1,2,3}; &#xff08;简化形式&#xff09;数据类型[] 数…

超赞!只需粘贴复制超赞,视频快速转换成文章

大家好&#xff01;我是闷声轻创&#xff01;是否还在为撰写高质量的文章而熬夜奋战&#xff1f;今天&#xff0c;我要给你们带来一个超级棒的消息——视频变文章的神奇工具&#xff0c;让你的创作之路从此不再艰辛&#xff01; 视频素材的宝藏——油管&#xff08;YTB&#xf…

2024年了还在学pytestday1

1、按照博主的说法&#xff0c;提出疑问&#xff1a;应该在电脑本地终端安装还是在pythoncharm终端安装&#xff1f; ------在pythoncharm终端安装就行 避免老是忘记&#xff0c;还是记下来比较好。 2、在公司安装不成功&#xff0c;换豆瓣源也不行&#xff0c;连接手机热点尝…

Linux--安装VMware步骤

安装VMware VMware Desktop Hypervisors for Windows, Linux, and Mac 复制链接打开浏览器下载即可 从官网下载软件&#xff0c;完成后为确保后续正常使用&#xff0c;需要检查虚拟网卡是否安装完成 检查虚拟网卡的安装步骤 Windows--设置--高级设置--网络适配器--看是否有显…

STM32杂交版(HAL库、音乐盒、闹钟、点阵屏、温湿度)

一、设计描述 本设计精心构建了一个以STM32MP157A高性能单片机为核心控制单元的综合性嵌入式系统。该系统巧妙融合了蜂鸣器、数码管显示器、点阵屏、温湿度传感器、LED指示灯以及按键等多种外设模块&#xff0c;形成了一个功能丰富、操作便捷的杂交版智能设备。通过串口…

vue2学习笔记-官网使用指南和搭建开发环境

官网使用指南 官网地址&#xff1a;介绍 — Vue.js 1、学习 1.1 教程和API 最重要的两个板块。API是VUE的字典&#xff0c;需要时来查阅。 1.2、风格指南 如何写出风格优雅的VUE代码。规则分为四类&#xff1a;必要的&#xff0c;强烈推荐、推荐、谨慎使用。 1.3、示例 …

初始网络知识

前言&#x1f440;~ 上一章我们介绍了使用java代码操作文件&#xff0c;今天我们来聊聊网络的一些基础知识点&#xff0c;以便后续更深入的了解网络 网络 局域网&#xff08;LAN&#xff09; 广域网&#xff08;WAN&#xff09; 路由器 交换机 网络通信基础 IP地址 端…

PCI PTS 硬件安全模块(HSM)模块化安全要求 v5.0

符合条件的 PCI SSC 利益相关者在 30 天的意见征询 (RFC) 期间审查 PCI PTS 硬件安全模块 (HSM) 模块化安全要求 v5.0 草案并提供反馈。 PCI PTS 硬件安全模块(HSM)模块化安全要求 v5.0图 从 7 月 8 日到 8 月 8 日&#xff0c;邀请符合条件的 PCI SSC 利益相关者在 30 天的意见…

C语言 结构体和共用体——结构体所占内存的字节数

目录 结构体所占内存的字节数 结构体所占内存的字节数

Unity之OpenXR+XR Interaction Toolkit实现 Gaze眼部追踪

使用 Unity OpenXR 实现Gaze眼部追踪 在虚拟现实(VR)和增强现实(AR)应用中,眼动追踪是一项强大而受欢迎的技术。它可以让开发者更好地理解用户的注意力和行为,并创造出更加沉浸和智能的体验。在本文中,我们将探讨如何使用 Unity OpenXR 实现Gaze眼部追踪功能。 Unity …

Linux文件:EXT2文件系统工作原理 软硬链接

Linux文件&#xff1a;文件系统究竟是什么&#xff1f;如何管理文件&#xff1f; 前言一、磁盘结构、存储策略1.1 磁盘存储结构1.2 磁盘存储策略1.3 磁盘的逻辑存储结构 二、如何管理磁盘文件三、如何管理组3.1 每个组保存的数据种类3.2 如何管理数据1、节点表&#xff08;inod…

智慧城市可视化页面怎么做?免费可视化工具可以帮你

智慧城市是一个综合性的概念&#xff0c;广泛应用于各个领域&#xff0c;如基础设施建设、信息化应用、产业经济发展、市民生活品质等。 可视化页面的制作也是一个综合性的过程&#xff0c;需要确定展示内容、数据收集与处理、设计可视化元素等多个环节紧密配合。 1. 明确展示…

从零开始开发视频美颜SDK:实现直播美颜效果

因此&#xff0c;开发一款从零开始的视频美颜SDK&#xff0c;不仅可以节省成本&#xff0c;还能根据具体需求进行个性化调整。本文将介绍从零开始开发视频美颜SDK的关键步骤和实现思路。 一、需求分析与技术选型 在开发一款视频美颜SDK之前&#xff0c;首先需要进行详细的需求…

python对点云可视化设置颜色

1、背景介绍 点云分类/分割时&#xff0c;常需要对分类结果进行可视化&#xff0c;其中给点云赋予不同颜色是一种最直接方法。介绍基于python中matplotlib进行点云颜色渲染显示。 2、点云颜色渲染 2.1 有限种颜色渲染 matplotlib在点云颜色渲染时&#xff0c;使用表示颜色的关…

【代码随想录】【算法训练营】【第65天】 [卡码94]城市间货物运输I

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 65&#xff0c;周四&#xff0c;继续ding~ [卡码94] 城市间货物运输I 题目描述 卡码94 城市间货物运输I 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#xff1a; 代码实现 C语言 Be…

快递查询|阿里云实现调用API接口

整体请求流程 介绍&#xff1a; 本次解析通过阿里云云市场的云服务来实现程序中对快递包裹实时监控&#xff0c;首先需要准备选择一家可以提供快递查询的商品。 https://market.aliyun.com/apimarket/detail/cmapi00065859#skuyuncode5985900001 步骤1: 选择商品 如图点击…

网站外链还有没有作用

前言 还记得“内容为王&#xff0c;外链为皇”这句话吗&#xff1f;在以前网站外链是网站优化中非常主要的环节。那时候做一个网站&#xff0c;只要不停的发外链&#xff0c;收录就不会差&#xff0c;于是大部分站长都使劲发外链。 有市场就有商场&#xff0c;大家都看到外链…

【国内超大型智能算力中心建设白皮书 2024】_智算中心算力规划

文末有福利&#xff01; 智算中心建设通过领先的体系架构设计&#xff0c;以算力基建化为主体、以算法基建化为引领、以服务智件化为依托&#xff0c;以设施绿色化为支撑&#xff0c;从基建、硬件、软件、算法、服务等全环节开展关键技术落地与应用。 一、体系架构 &#xf…