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

news2024/9/22 1:25:38

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.coloradmin.cn/o/1921764.html

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

相关文章

谷粒商城踩坑记录-网关服务启动报错

文章目录 一&#xff0c;错误表现二&#xff0c;错误原因三&#xff0c;解决方案1&#xff0c;排除无关依赖2&#xff0c;调整依赖关系 一&#xff0c;错误表现 在启动Spring Cloud Gateway服务时&#xff0c;控制台输出了一系列错误信息&#xff0c;指出应用程序未能成功启动…

单元测试Mockito笔记

文章目录 单元测试Mockito1. 入门1.1 什么是Mockito1.2 优势1.3 原理 2. 使用2.0 环境准备2.1 Mock1) Mock对象创建2) 配置Mock对象的行为(打桩)3) 验证方法调用4) 参数匹配5) 静态方法 2.2 常用注解1) Mock2) BeforeEach 与 BeforeAfter3) InjectMocks4) Spy5) Captor6) RunWi…

在 Java 中:为什么不能在 static 环境中访问非 static 变量?

在 Java 中&#xff1a;为什么不能在 static 环境中访问非 static 变量&#xff1f; 1、静态&#xff08;static&#xff09;变量2、非静态&#xff08;非static&#xff09;变量3、为什么不能访问&#xff1f;4、如何访问&#xff1f;5、总结 &#x1f496;The Begin&#x1f…

百度2025校园招聘内推开始啦

百度2025校园招聘内推开始啦&#xff0c;快来投递你心仪的职位吧&#xff08; 网申链接地址&#xff1a;https://talent.baidu.com/jobs/list?recommendCodeIZB4S3&recruitTypeGRADUATE &#xff09;填入内推码&#xff0c;完成投递&#xff0c;get内推绿色通道~我的内推码…

GEO的表达矩阵的探针ID转换成基因名称教程

GEO的表达矩阵的探针ID转换成基因名称教程 前情回顾 根据GSE id自动下载处理GEO数据(必须要运行的模块) 该模块的运行窗口截图 该模块的教程 知乎地址&#xff1a;根据GEO的GSE数据集编号自动下载和处理GEO数据教程: https://zhuanlan.zhihu.com/p/708053447 该根据GSE id…

第1章 初识 Express

1.1 什么是 Express Express 是一个简洁而灵活的 Node.js Web 应用框架&#xff0c;提供了一系列强大的特性用于开发 Web 和移动应用。它基于 Node.js 构建&#xff0c;并且与 Node.js 的非阻塞 I/O 模型无缝集成&#xff0c;使其非常适合于构建高性能的 Web 应用。 主要特点…

idea修改全局配置、idea中用aliyun的脚手架,解决配置文件中文乱码

idea修改全局配置 idea中用aliyun的脚手架&#xff0c;创建springBoot项目 解决配置文件中文乱码

【笔记】虚拟机中的主从数据库连接实体数据库成功后的从数据库不同步问题解决方法2

错误&#xff1a; Last_Errno: 1008 Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction ANONYMOUS at source log mysql-bin.000014, end_log_pos 200275. See error lo…

JavaWeb(四:Ajax与Json)

一、Ajax 1.定义 Ajax&#xff08;Asynchronous JavaScript And XML&#xff09;&#xff1a;异步的 JavaScript 和 XML AJAX 不是新的编程语言&#xff0c;指的是⼀种交互方式&#xff1a;异步加载。 客户端和服务器的数据交互更新在局部页面的技术&#xff0c;不需要刷新…

剪画小程序:职场上如何提高工作效率?

亲爱的宝子们&#xff0c;不知道你们有没有遇到过这样的情况&#xff1a; 在公司里&#xff0c;老板突然让你整理一份国外产品介绍视频里的关键信息&#xff0c;可那是外语的&#xff0c;听得你一头雾水。 这时候&#xff0c;有什么方法或办法&#xff01;能快速准确地将视频中…

02对话系统---图片的导入

样式 例&#xff1a; 1.<styleH1> Hellow <styleH1>world 效果&#xff1a; 样式表 路径&#xff1a; 插入图片 插入默认图片 2.<sprite0> text<sprite0> 效果&#xff1a; 图集路径&#xff1a; 导入单个图片 给…

飞腾平台虚拟机组播性能调优指南

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

网优学习干货:xx5G速率优化现场实战版

速率概述 无线网络仍然是5G网络能力最容易受限的环节&#xff0c;无线网络技术的应用将最终决定5G网络能力的木桶深度。移动通信中传统关键技术在5G将会继续使用。5G NR在继承了LTE原有部分技术基础上&#xff0c;采用了一些技术演进和新技术创新。比如NR继承了LTE的OFDM和SC-…

内网安全:权限维持的各种姿势

1.Linux权限维持 2.Windows权限维持 目录&#xff1a; 一.Linux权限维持&#xff1a; 1.webshell&#xff1a; 2.定时任务&#xff1a; 3.SUID后门&#xff1a; 4.SSH Key免密登录后门&#xff1a; 5.添加用户后门&#xff1a; 二.Windows权限维持 1.计划任务后门&…

活用 localStorage

我维护的这款工具 https://editor.yunwow.cn/ 已经帮我写了 7 篇文章了&#xff0c; 用起来很顺手&#xff0c;因此我打算再给它升级下让它更方便&#xff0c;我决定要给它加个本地缓存功能。我给它提的要求是&#xff1a; 1. 至少能缓存 5 篇文章 2. 能有选择的加载模板 3…

C语言:指针详解(4)

作者本人由于大一下学期事情繁多&#xff0c;大部分时间都在备赛&#xff0c;没有时间进行博客撰写&#xff0c;如今已经到了暑假时间&#xff0c;作者将抓紧每一天的时间进行编程语言的学习&#xff0c;由于目前作者已经进行到了C的学习&#xff0c;C语言阶段的学习与初阶数据…

QT之嵌入外部第三方软件到本窗体中

一、前言 使用QT开发&#xff0c;有时需要调用一些外部程序&#xff0c;但是单独打开一个外部窗口有的场合很不合适&#xff0c;最好是嵌入到开发的QT程序界面中。还有就是自己开发的n个程序&#xff0c;一个主程序托n个子程序&#xff0c;为了方便管理将各个程序独立&#xf…

JMeter CSV 参数文件的使用教程

在 JMeter 测试过程中&#xff0c;合理地使用参数化技术是提高测试逼真度的关键步骤。本文将介绍如何通过 CSV 文件实现 JMeter 中的参数化。 设定 CSV 文件 首先&#xff0c;构建一个包含需要参数化数据的 CSV 文件。打开任何文本编辑器&#xff0c;输入希望模拟的用户数据&…

烟雾识别技术在火灾预防中的应用:思通数科大模型的力量

引言 火灾是导致生命财产损失的重大灾害之一。早期检测和快速响应是预防火灾和减少损失的关键。结合思通数科大模型的烟雾识别技术&#xff0c;为实时检测和精确定位烟雾来源提供了一种高效的解决方案。本文将探讨这一技术如何有效预防火灾并保障人员安全。 烟雾识别技术概述 …

Transformer——多头注意力机制(Pytorch)

1. 原理图 2. 代码 import torch import torch.nn as nnclass Multi_Head_Self_Attention(nn.Module):def __init__(self, embed_size, heads):super(Multi_Head_Self_Attention, self).__init__()self.embed_size embed_sizeself.heads headsself.head_dim embed_size //…