【C语言 | 指针】数组参数 和 指针参数

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍C语言的数组参数 和 指针参数🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭

本文未经允许,不得转发!!!


在这里插入图片描述

🎄一、概述

在使用函数时,参数分为形参和实参。
形参是指声明或定义函数时的参数;
实参是在调用函数时主调函数传递过来的实际值。

本文主要介绍C语言中函数参数为数组或者指针时,一些容易令人混淆的概念。在继续学习之前不妨思考一下几个问题:
1.数组可以作为函数形参吗?
2.数组可以作为函数实参吗?
3.指针作为函数参数,需要注意什么?


在这里插入图片描述

🎄二、一维数组参数

学习数组参数前,先看下面代码是否有问题:
这里fun函数的形参看起来应该是一个包含10个char型的数组,然后在调用fun函数时,把数组b作为实参传入函数。
可事实并不是这样的,接着往下看。

void fun(char a[10])
{
	char c = a[3];
}
int main()
{
	char b[10] = "abcdefg";
	fun(b[10]);
	return 0;
}

事实上,上面代码编译后,会产生一个警告和一个注意,编译打印:
在这里插入图片描述
这个warning说,调用fun(b[10])时,传入的指针来自不带强制转换的整型数。意思是,编译器把b[10]当前一个整型数,并且调用fun(b[10])时,会将b[10]转换成指针。
这里的note,提示我们void fun(char a[10])需要一个char*的实参,但给的却是char

从这个例子,我们可以清楚下面几点:
1、调用fun(b[10]);时,b[10]并不是一个数组,而是b数组的一个元素,类型是char;
2、编译器并不管b[10]是否越界,只是把它当前一个数组元素;
3、void fun(char a[10])需要的参数是一个char *指针。
4、C语言中,无法将一个数组直接传递给函数。

✨2.1 一维数组形参

C语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。

编译器这么做是有原因的。在 C 语言中,所有非数组形式的数据实参均以传值形式(对实参做一份拷贝并传递给被调用的函数,函数不能修改作为实参的实际变量的值,而只能修改传递给它的那份拷贝)调用。然而,如果要拷贝整个数组,无论在空间上还是在时间上,其开销都是非常大的。更重要的是,在绝大部分情况下,你其实并不需要整个数组的拷贝,你只想告诉函数在那一刻对哪个特定的数组感兴趣。这样的话,为了节省时间和空间,提高程序运行的效率,于是就有了上述的规则。同样的,函数的返回值也不能是一个数组,而只能是指针。

看下面例子,在fun函数中,打印形参的a的大小,发现等于指针大小sizeof(int*)。

#include <stdio.h>
void fun(int a[10])
{
	printf("a=%p sizeof(a)=%lu\n", a, sizeof(a));
}
int main()
{
	int a[10] = {1,2,3,4,5,6,7,8,9,0};
	printf("a=%p sizeof(int*)=%lu\n", a, sizeof(int*));
	fun(a);
	return 0;
}

既然跟数组大小无关的话,fun函数可以写成下面的形式:

void fun(int a[])
{
	printf("a=%p sizeof(a)=%lu\n", a, sizeof(a));
}

因为编译器把它当成指针,所以我们也可以直接把fun函数形参写成指针,如下:

void fun(int *a)
{
	printf("a=%p sizeof(a)=%lu\n", a, sizeof(a));
}

所以,数组形参的这三种写法都是一样的:

1void fun(int a[10])
2void fun(int a[])
3void fun(int *a)

✨2.2 一维数组实参

由前一小节,应该可以很清楚知道,无法向函数传递一个数组。所以就没有数组实参的说法。

那么,将数组名作为实参传给函数,又是什么意思呢?

其实,数组名就是数组首个元素的地址,是一个指针,数组形参的本质也是一个指针,将数组名作为实参传给函数,实际上就是将一个指针赋值给另一个指针,是符合C语言规定的。


在这里插入图片描述

🎄三、一级指针参数

✨3.1 一级指针形参

形参是对实参的一份拷贝(复制),并不是实参本身。对于指针参数,也是如此,所以无法将指针本身传递给函数。
看例子:

#include <stdio.h>
void fun(int *p2)
{
	printf("&p2=%p p2=%p\n", &p2, p2);
}
int main()
{
	int i=10;
	int *p = &i;
	printf("&p=%p p=%p\n", &p, p);
	fun(p);
	return 0;
}

运行结果如下:
在这里插入图片描述
可以看到指针变量 p 的地址是0x7fff699c24e8,调用fun(p),传递给形参p2,p2的地址则是0x7fff699c24c8,它们不是同一个变量;但它们的值都是0x7fff699c24e4。

✨3.2 一级指针实参

从前面可知,指针实参只把指针的值给到形参,那如果想改变实参的值需要怎么做?

  • 1、用return
    char * GetMemory(char * p, int num)
    {
    	p = (char *)malloc(num*sizeof(char));
    	return p;
    }
    int main()
    {
    	char *str = NULL;
    	str = GetMemory( str, 10;
    	strcpy(str,”hello”);
    	free( str);
    	return 0;
    }
    
  • 2、使用二级指针
    void GetMemory( char ** p, int num)
    {
    	*p = (char *)malloc(num*sizeof(char));
    	return p;
    }
    int main()
    {
    	char *str = NULL;
    	GetMemory( &str, 10;
    	strcpy(str,”hello”);
    	free( str);
    	return 0;
    }
    

在这里插入图片描述

🎄四、总结

👉本文介绍C语言中,数组参数 和 指针参数一些注意点。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wkd_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值