阐述 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.rhkb.cn/news/373375.html

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

相关文章

从海上长城到数字防线:视频技术在海域边防现代化中的创新应用

随着全球化和科技发展的加速&#xff0c;海域安全问题日益凸显其重要性。海域边防作为国家安全的第一道防线&#xff0c;其监控和管理面临着诸多挑战。近年来&#xff0c;视频技术的快速发展为海域边防场景提供了新的解决方案&#xff0c;其高效、实时、远程的监控特点极大地提…

增强现实(AR)与虚拟现实(VR)的区别?

随着科技的飞速发展&#xff0c;增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;技术在各个领域展现出巨大的潜力和应用前景。这两种技术虽然在体验和实现方式上有所不同&#xff0c;但都为用户提供了全新的感知体验。本文将详细解析AR和VR的概念、区…

《Windows API每日一练》9.13资源-鼠标位图和字符串

鼠标指针位图&#xff08;Mouse Cursor Bitmap&#xff09;是用于表示鼠标指针外观的图像。在 Windows 窗口编程中&#xff0c;可以使用自定义的鼠标指针位图来改变鼠标的外观&#xff0c;并提供更加个性化的用户体验。 ■以下是一些与鼠标指针位图相关的要点&#xff1a; ●…

17集 如何用ESP-IDF编译ESP-DL深度学习工程-《MCU嵌入式AI开发笔记》

17集 如何用ESP-IDF编译ESP-DL深度学习工程-《MCU嵌入式AI开发笔记》 参考文档&#xff1a;ESP-DL 用户指南&#xff1a; https://docs.espressif.com/projects/esp-dl/zh_CN/latest/esp32/index.html 和https://docs.espressif.com/projects/esp-dl/zh_CN/latest/esp32/get-s…

详细分析@FunctionalInterface的基本知识(附Demo)

目录 前言1. 基本知识2. Demo 前言 Java的基本知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;Spring框架从入门到学精&#xff08;全&#xff09; 1. 基本知识 FunctionalInterface 是 Java 8 引入的一个注…

gitee上传和下载idea项目的流程

环境&#xff1a;idea2022 一、上传项目 1、在gitee中新建一个仓库。 2、打开所要上传的项目的文件夹&#xff0c;点击Git Bash&#xff0c;生成.git文件夹。 3、在idea中打开所要上传的项目&#xff0c;在控制台的Terminal菜单中&#xff0c;输入git add . (注意&#xf…

爆破器材期刊

《爆破器材》简介   《爆破器材》自1958年创刊以来&#xff0c;深受广大读者喜爱&#xff0c;是中国兵工学会主办的中央级技术刊物&#xff0c;在国内外公开发行&#xff0c;近几年已发行到10个国家和地区。《爆破器材》杂志被美国著名检索机构《化学文摘》&#xff08;CA&a…

【持续集成_03课_Linux部署Sonar+Gogs+Jenkins】

一、通过虚拟机搭建Linux环境-CnetOS 1、安装virtualbox&#xff0c;和Vmware是一样的&#xff0c;只是box更轻量级 1&#xff09;需要注意内存选择&#xff0c;4G 2、启动完成后&#xff0c;需要获取服务器IP地址 命令 ip add 服务器IP地址 通过本地的工具&#xff0c;进…

无人机对地面运动目标定位---获取目标的移动方向和速度

目录 一、引子 我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位&#xff0c;当前&#xff0c;我们已经获得了每张相片上该目标的三维坐标&#xff0c;并且知道该无人机在飞行过程中拍照的时间间隔&#xff0c;那么我们就可以通过一定的计算&#xff0c;得…

Zabbix Sia Zabbix 逻辑漏洞(CVE-2022-23134)

前言 CVE-2022-23134是一个中等严重度的漏洞&#xff0c;影响Zabbix Web前端。这个漏洞允许未经身份验证的用户访问setup.php文件的某些步骤&#xff0c;这些步骤通常只对超级管理员开放。利用这个漏洞&#xff0c;攻击者可以通过跳过某些步骤来重新配置Zabbix前端&#xff0c…

kafka系列之offset超强总结及消费后不提交offset情况的分析总结

概述 每当我们调用Kafka的poll()方法或者使用Spring的KafkaListener(其实底层也是poll()方法)注解消费Kafka消息时&#xff0c;它都会返回之前被写入Kafka的记录&#xff0c;即我们组中的消费者还没有读过的记录。 这意味着我们有一种方法可以跟踪该组消费者读取过的记录。 如前…

List、Map、Set 接口在Java中的存取元素特点

List、Map、Set 接口在Java中的存取元素特点 1、List 接口2、Map 接口3、Set 接口4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java中&#xff0c;List、Map和Set是三个最常用的集合接口。它们各自有不同的特点和用途&#xff…

如何在 Microsoft Edge 上使用开发人员工具

Microsoft Edge 提供了一套强大的开发人员工具&#xff0c;可帮助 Web 开发人员检查、调试和优化他们的网站或 Web 应用程序。 无论您是经验丰富的 Web 开发人员还是刚刚起步&#xff0c;了解如何有效地使用这些工具都可以对开发过程产生重大影响。 在本文中&#xff0c;我们…

Camera Raw:常规工具

在 Camera Raw 窗口右下角提供了四个常用的工具&#xff0c;它们分别是&#xff1a;缩放工具、抓手工具、切换取样器叠加以及切换网格叠加工具。 ◆ ◆ ◆ 缩放工具 Zoom Tool 用于放大或缩小预览图像&#xff0c;便于查看和编辑细节。 快捷键&#xff1a;Z 1、双击“缩放工具…

[21] Opencv_CUDA应用之使用Haar级联的对象检测

Opencv_CUDA应用之使用Haar级联的对象检测 Haar级联使用矩形特征来检测对象,它使用不同大小的矩形来计算不同的线和边缘特征。矩形包含一些黑色和白色区域,如下图所示,它们在图像的不同位置居中 类Haar特征检测算法的思想是计算矩形内白色像素和黑色像素之间的差异这个方法的…

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃 import java.net.InetAddress;public class GetHostIp {public static void main(String[] args) {try {long start System.currentTimeMillis();String ipAddress InetAddress.getLocalHost().getHostA…

clean code-代码整洁之道 阅读笔记(第十七章 终章)

大纲 第十七章 味道与启发 17.1 注释 C1&#xff1a;不恰当的信息 C2&#xff1a;废弃的注释 C3&#xff1a;冗余注释 C4&#xff1a;糟糕的注释 C5&#xff1a;注释掉的代码 17.2 环境 E1&#xff1a;需要多步才能实现的构建 E2&#xff1a;需要多步才能做到的测试 …

51单片机嵌入式开发:2、STC89C52操作GPIO口LED灯

STC89C52操作GPIO口LED灯 1 芯片介绍1.1 芯片类型1.2 芯片系列说明 2 GPIO引脚寄存器说明3 GPIO操作3.1 GPIO输入3.2 GPIO输出3.3 GPIO流水灯3.4 Protues仿真 4 总结 1 芯片介绍 1.1 芯片类型 芯片采用宏晶科技品牌下的STC89C52RC单片机 选择STC89C52RC系列STC89C58RD系列单片…

基于Java的学生选课系统

第1章 系统概述 1.1概述 背景&#xff1a;随着计算机网络技术的发展&#xff0c;Web 数据库技术已成为应用最为广泛的网站架构基础技术。学生选课系统作为教育单位不可缺少的部分&#xff0c;其内容对于学校的决策者和管理者至关重要。传统的人工管理方式存在效率低、保密性差等…

LabVIEW平台从离散光子到连续光子的光子计数技术

光子计数技术用于将输入光子数转换为离散脉冲。常见的光子计数器假设光子是离散到达的&#xff0c;记录到来的每一个光子。但是&#xff0c;当两个或多个光子同时到达时&#xff0c;计数器会将其记录为单个脉冲&#xff0c;从而只计数一次。当连续光子到达时&#xff0c;离散光…