• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C语言 指针变量作为函数参数详解

C语言 指针变量作为函数参数详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c语言指针变量,c语言定义指针变量,c语言指针变量赋值,c语言中指针变量,c语言指针详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。

像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。

有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。

有些初学者可能会使用下面的方法来交换两个变量的值:

#include <stdio.h>
void swap(int a, int b){
  int temp; //临时变量
  temp = a;
  a = b;
  b = temp;
}
int main(){
  int a = 66, b = 99;
  swap(a, b);
  printf("a = %d, b = %d\n", a, b);
  return 0;
}
</div>

运行结果:

a = 66, b = 99

从结果可以看出,a、b 的值并没有发生改变,交换失败。这是因为 swap() 函数内部的 a、b 和 main() 函数内部的 a、b 是不同的变量,占用不同的内存,它们除了名字一样,没有其他任何关系,swap() 交换的是它内部 a、b 的值,不会影响它外部(main() 内部) a、b 的值。

改用指针变量作参数后就很容易解决上面的问题:

#include <stdio.h>
void swap(int *p1, int *p2){
  int temp; //临时变量
  temp = *p1;
  *p1 = *p2;
  *p2 = temp;
}
int main(){
  int a = 66, b = 99;
  swap(&a, &b);
  printf("a = %d, b = %d\n", a, b);
  return 0;
}
</div>

运行结果:

a = 99, b = 66

调用 swap() 函数时,将变量 a、b 的地址分别赋值给 p1、p2,这样 *p1、*p2 代表的就是变量 a、b 本身,交换 *p1、*p2 的值也就是交换 a、b 的值。函数运行结束后虽然会将 p1、p2 销毁,但它对外部 a、b 造成的影响是“持久化”的,不会随着函数的结束而“恢复原样”。

需要注意的是临时变量 temp,它的作用特别重要,因为执行*p1 = *p2;语句后 a 的值会被 b 的值覆盖,如果不先将 a 的值保存起来以后就找不到了。

用数组作函数参数

数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。下面的例子定义了一个函数 max(),用来查找数组中值最大的元素:

#include <stdio.h>
int max(int *intArr, int len){
  int i, maxValue = intArr[0]; //假设第0个元素是最大值
  for(i=1; i<len; i++){
    if(maxValue < intArr[i]){
      maxValue = intArr[i];
    }
  }
  
  return maxValue;
}
int main(){
  int nums[6], i, maxValue;
  int len = sizeof(nums)/sizeof(int);
  //读取用户输入的数据并赋值给数组元素
  for(i=0; i<len; i++){
    scanf("%d", nums+i);
  }
  printf("Max value is %d!\n", max(nums, len));
  return 0;
}
</div>

运行结果:

12 55 30 8 93 27↙
Max value is 93!

参数 intArr 仅仅是一个数组指针,在函数内部无法通过这个指针获得数组长度,必须将数组长度作为函数参数传递到函数内部。数组 nums 的每个元素都是整数,scanf() 在读取用户输入的整数时,要求给出存储它的内存的地址,nums+i就是第 i 个数组元素的地址。

用数组做函数参数时,参数也能够以“真正”的数组形式给出。例如对于上面的 max() 函数,它的参数可以写成下面的形式:

int max(int intArr[6], int len){
  int i, maxValue = intArr[0]; //假设第0个元素是最大值
  for(i=1; i<len; i++){
    if(maxValue < intArr[i]){
      maxValue = intArr[i];
    }
  }
  return maxValue;
}
</div>

int intArr[6]好像定义了一个拥有 6 个元素的数组,调用 max() 时可以将数组的所有元素“一股脑”传递进来。

读者也可以省略数组长度,把形参简写为下面的形式:

int max(int intArr[], int len){
  int i, maxValue = intArr[0]; //假设第0个元素是最大值
  for(i=1; i<len; i++){
    if(maxValue < intArr[i]){
      maxValue = intArr[i];
    }
  }
  return maxValue;
}
</div>

int intArr[]虽然定义了一个数组,但没有指定数组长度,好像可以接受任意长度的数组。

实际上这两种形式的数组定义都是假象,不管是int intArr[6]还是int intArr[]都不会创建一个数组出来,编译器也不会为它们分配内存,实际的数组是不存在的,它们最终还是会转换为int *intArr这样的指针。这就意味着,两种形式都不能将数组的所有元素“一股脑”传递进来,大家还得规规矩矩使用数组指针。

int intArr[6]这种形式只能说明函数期望用户传递的数组有 6 个元素,并不意味着数组只能有 6 个元素,真正传递的数组可以有少于或多于 6 个的元素。

需要强调的是,不管使用哪种方式传递数组,都不能在函数内部求得数组长度,因为 intArr 仅仅是一个指针,而不是真正的数组,所以必须要额外增加一个参数来传递数组长度。

C语言为什么不允许直接传递数组的所有元素,而必须传递数组指针呢?

参数的传递本质上是一次赋值的过程,赋值就是对内存进行拷贝。所谓内存拷贝,是指将一块内存上的数据复制到另一块内存上。

对于像 int、float、char 等基本类型的数据,它们占用的内存往往只有几个字节,对它们进行内存拷贝非常快速。而数组是一系列数据的集合,数据的数量没有限制,可能很少,也可能成千上万,对它们进行内存拷贝有可能是一个漫长的过程,会严重拖慢程序的效率,为了防止技艺不佳的程序员写出低效的代码,C语言没有从语法上支持数据集合的直接赋值。

除了C语言,C++、Java、Python 等其它语言也禁止对大块内存进行拷贝,在底层都使用类似指针的方式来实现。

以上就对C 语言指针变量作为函数参数进行的资料整理,后续继续整理相关知识,谢谢大家对本站的支持!

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C语言 指针变量作为函数参数详解
  • C 语言指针变量的运算详解
  • C 语言指针变量详细介绍

相关文章

  • 2017-05-28C 语言基础教程(我的C之旅开始了)[九]
  • 2017-05-28解析C语言基于UDP协议进行Socket编程的要点
  • 2017-05-28C++派生类与基类的转换规则
  • 2017-05-28深入C++拷贝构造函数的总结详解
  • 2017-05-28用C语言模仿Python函数的实例
  • 2017-05-28C/C++ 中sizeof('a')对比详细介绍
  • 2017-05-28C++编程中的函数指针初步解析
  • 2017-05-28c++ 构造函数中调用虚函数的实现方法
  • 2017-05-28C++中的异常处理机制详解
  • 2017-05-28浅析C语言中堆和栈的区别

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 如何统计在一篇文章中某个单词出现了几次,以及第一次出现的位置
    • 编译错误error: stray ‘\343’in program的解决方法
    • C++空类默认函数详细解析
    • C++实现闹钟程序的方法
    • 探讨C语言的那些小秘密之断言
    • C++利用MySQL API连接和操作数据库实例详解
    • 深入jaxb xjc编码问题的详细介绍
    • c语言链表基本操作(带有创建链表 删除 打印 插入)
    • Codeforces 842A. Kirill And The Game (暴力算法比较)
    • C语言 实现遍历一个文件夹的所有文件

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有