阐述 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;变量赋值…

ubuntu系统下使用gelsight

一、背景 创建 conda create -n gelsight python3.8 conda activate gelsight cd GelSight/gsrobotics-main/demos/marker_tracking/ python3 mean_shift_marker_tracking.py ModuleNotFoundError: No module named ‘numpy’ pip3 install numpy ModuleNotFoundError: N…

【核心笔记】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…

反馈神经网络与不同类型的神经网络:BP神经网络,深度感知机,CNN,LSTM

反馈神经网络与不同类型的神经网络&#xff1a;BP神经网络&#xff0c;深度感知机&#xff0c;CNN&#xff0c;LSTM 在神经网络的研究和应用中&#xff0c;我们经常听到BP神经网络、深度感知机&#xff08;MLP&#xff09;、卷积神经网络&#xff08;CNN&#xff09;、长短期记…

对象转换传输规范SpringBeanUtil工具类封装

对象转换传输规范SpringBeanUtil工具类封装 前言 上一集我们已经完成了SpringBoot3.X MybatisPlus的逆向工程,这一集我们将会完成对象转换传输规范SpringBeanUtil工具类的封装。 在讲主要内容的之前,我们将会补充一些小知识。 N方库 在软件开发中&#xff0c;库&#xff08…

TS-类型别名和接口的区别

TypeScript中的类型别名&#xff08;Type Alias&#xff09; 和 接口&#xff08;Interface&#xff09; 都是用来自定义类型的工具&#xff0c;但他们在语法和使用场景上有一些区别。 扩展和合并 类型别名&#xff1a;不能直接扩展和合并&#xff0c;但可以通过交叉类型来实现…

2024年了还在学pytestday1

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

LangChain 语言 —— LCEL

文章目录 一、概述二、快速开始1、invoke 一个 runable2、batch 一个 runable3、stream 一个 runable4、将runables组合起来5、并行调用可运行文件6、将任何function转换为可runable7、合并输入和输出字典8、将输入字典包含在输出字典中9、添加默认调用参数 一、概述 LangChain…

华为机考真题 -- 靠谱的车

题目描述: 程序员小明打了一辆出租车去上班。出于职业敏感,他注意到这辆出租车的计费表有点问题,总是偏大。出租车司机解释说他不喜欢数字 4,所以改装了计费表,任何数字位置遇到数字 4 就直接跳过,其余功能都正常。 比如: 1. 23 再多一块钱就变为 25; 2. 39 再多一块钱…

大象资讯 | IvorySQL 3.3 发版

IvorySQL 3.3 于 2024.07.11 日发版&#xff0c;该版本基于 PostgreSQL 16.3&#xff0c;修复若干问题。 IvorySQL 是一款以 PostgreSQL 为基础进行开发&#xff0c;并且兼容 Oracle 的开源数据库。该项目是在 Apache 2.0 许可证下发布的&#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 天的意见…

【linux】服务器创建RAID1(软件配置RAID1)

【linux】服务器创建RAID1(软件配置RAID1) 文章目录 【linux】服务器创建RAID1(软件配置RAID1)一、配置介绍raid介绍raid类型RAID 0:RAID 1:RAID 5:RAID 6:二、配置RAID硬件RAID:软件RAID:三、软件配置RAID1(以linux为例)1.先进入管理员模式2.安装mdadm工具3.创建raid1数…

SSH服务器CBC漏洞(CVE-2008-5161)

漏洞简介 OpenSSH 是一种开放源代码的SSH协议的实现,初始版本用于OpenBSD平台,现在已经被移植到多种Unix/Linux类操作系统下,Linux环境中一般采用AES这种算法加密,AES有五种加密模式(CBC、ECB、CTR、OCF、CFB),系统默认会选择CBC的加密模式。 CBC模式是一种常用的对称…

存取款系统接口设计

题目描述&#xff1a; 设计一个存取款接口&#xff0c;入参是账户数组balances 与存取款请求体数组requests 对于取款要求判断&#xff1a; 当前余额不足&#xff0c;返回余额不足帐号 之前的取款时间在24之前的&#xff0c;在24小时之后返回上次取款额度的百分之2并向下取整。…