Bootstrap

c语言--指针作为函数参数传递

指针作为函数参数传递

目录

指针作为函数参数传递

 1.整形作为函数参数

1.1在函数中交换两个值的易发生错误的地方

2.数组作为参数传递



----------------------------------------记录一下学习过程----------------------------------------------------

                                           --------如有不足,还请斧正-------

 1.整形作为函数参数

先来看一下没有用到指针传递的函数:

对于初学者来说

void Funtion_1(int a) {
	a = 20;
}
void main() {
	int num = 10;
	Funtion_1(num);
	printf("改变后的值为:%d\n",num);
}

看到该函数,就会想到运行结果为

改变后的值为:20

实际上该函数运行的结果为:

改变后的值为:10

为什么我们明明已经把参数传到Funtion_1中了,还会这样呢?

这里就要引入两个概念:形参和实参,代码void Funtion_1(int a)里面的a是形参,而main函数里面给Funtion_1传递的num则为实参。

该程序运行时,首先会在内存中创建实参num=10,接着把实参传递到Funtion_1(int a)函数中,该传递是复制,即系统会开辟另一个地址给a 。这样就相当于有两个变量一个num ,一个a。在Funtion_1()中,改变的只是a,而对main()中的num没有影响,所以num的值没有改变。举个例子:把地址比作水桶,在main中创建了一个变量,即有个桶叫num,里面放着10L的水,我们将这个桶传给Funtion_1中,在Funtion_1中又新建了一个桶叫a,里面同样放着与num桶相同升数的水,即为10L,这时将桶a中的水更改为20L,a桶目前拥有20L水,但num桶却只有10L水,a桶的改变不会影响到num桶中水的改变,因为这是两个独立的桶      画图表示为:

那我们该怎么改变传进去的变量呢?

以桶为例子,如果我们能让a桶与Num桶合二为一,变成一个桶呢?那么我们改变a,则Num也会随之改变。

void Funtion_2(int *a) {
	*a = 20;
}
void main() {
	int num = 10;
	Funtion_2(&num);
	printf("改变后的值为:%d\n",num);
}

运行结果为: 

 改变后的值为:20

 为什么Funtion_2可以改变结果?

Funtion_2中接收的是一个指针变量,main中传递过去的是num的地址,funtion_2中接收到的则为num的地址,num与a都指向同一片空间,即都为同一个桶

由此可见,我们是否能改变数值,关键要看是值传递,还是址传递。值传递为复制个新的变量,新的变量修改后,并不会影响旧的变量;址传递,为把地址传递过去,两个变量共用同一处地址,做到一改全改。



1.1在函数中交换两个值的易发生错误的地方

void swap_1(int p1, int p2) {
	int p = p1;
	p1 = p2;
	p2 = p;
}
void swap_2(int* p1, int* p2) {
	int p= *p1;
	*p1 = *p2;
	*p2 = p;
}
void swap_3(int* p1, int* p2) {
	int* p= p1;
	p1 = p2;
	p2 = p;
}
void main() {
	int a, b, c, d;
	a = 1;b = 2;
	printf("改变前的a=%d,b=%d\n", a, b);
	swap_1(&a, &b);
	printf("swap_1改变后的a=%d,b=%d\n\n", a, b);
	a = 1; b = 2;
	printf("改变前的a=%d,b=%d\n", a, b);
	swap_2(&a, &b);
	printf("swap_2改变后的a=%d,b=%d\n\n", a, b);
	a = 1; b = 2;
	printf("改变前的a=%d,b=%d\n", a, b);
	swap_3(&a, &b);
	printf("swap_3改变后的a=%d,b=%d\n\n", a, b);
}

 接着看这些代码:

运行的结果为:

改变前的a=1,b=2
swap_1改变后的a=1,b=2

改变前的a=1,b=2
swap_2改变后的a=2,b=1

改变前的a=1,b=2
swap_3改变后的a=1,b=2

其中

swap_1,与Funtion_1中的错误一样,为值传递,所以不会交换a和b的值

swap_3, 首先将p1的地址赋值给p,接着将p2的地址赋值给p1,最后将p的地址(即最初p1的地址)赋值给p2。整个过程来说,即将a与b的地址互换,这里的地址交换并不会影响到main函数中的两个地址,所以不会交换a与b的值。涉及到的知识点:通过地址去改变值,通过地址的地址去改变地址的值。

我们将swap_3稍加修改

void swap_4(int** p1, int** p2) {
	int** p= *p1;
	*p1 = *p2;
	*p2 = p;
}
	int* aa = &a;
	int* bb = &b;
	swap_3(&aa, &bb);

改变前的a=1,b=2
swap_4改变后的a=1,b=2

--------------------------------------------------------------------------------------------------------------------------

2.数组作为参数传递

数组进行传参时,传递的数组的地址。

一维数组传参的基本形式:

void arr_1(int arr[3]) {
	for (int i = 0; i <= 2;i++) {
		printf("%d ",arr[i]);
	}
}
void arr_2(int arr[]) {
	for (int i = 0; i <= 2; i++) {
		printf("%d ", arr[i]);
	}
}
void arr_3(int *arr) {
	for (int i = 0; i <= 2; i++) {
		printf("%d ", arr[i]);
	}
}
void main() {
	int arr[3] = {1,2,3};
	printf("调用arr_1:");
	arr_1(arr);
	printf("\n调用arr_2:");
	arr_2(arr);
	printf("\n调用arr_3:");
	arr_3(arr);
}

重点在于在函数中修改数组的值:

一般情况下,数组名是数组的首元素的地址:

int arr[3]={1,2,3};
printf("arr:%d",arr);

运行结果->  1
void arr_3(int *arr) {
	for (int i = 0; i <= 2; i++) {
		printf("%d ", arr[i]);
        
	}
}
void ArrayChange(int *arr,int k) {
	for (int i = 0; i <= k - 1;i++) {
		//arr[i] = i * 5;
        *(arr+i)=i*5;
	}
}
void main() {
	int arr[3] = {1,2,3};
	printf("修改前:\n");
	arr_3(arr);
	ArrayChange(arr, sizeof(arr) / sizeof(arr[0]));
	printf("\n修改后:\n");
	arr_3(arr);
}

由于数组传递过来的是数组的首地址,所以ArrayChange中接收到的也为数组的地址,故为址传递,由前面可知我们可以通过地址去修改mian函数中的值。

;