[C语言] 函数实参与形参详解

文章目录

实参的概念示例:实参传递

形参的概念形参的语法结构示例:形参接收实参

实参与形参的关系实参与形参的传递过程示例:实参与形参的关系

实参和形参的传递方式值传递示例:值传递

指针传递示例:指针传递

示例讲解示例1:计算两数之和(值传递)示例2:交换两个数的值(指针传递)示例讲解

扩展内容:指针与参数传递传递数组示例:传递数组

解释

传递结构体指针示例:传递结构体指针

指针与实参传递的总结

总结

在C语言编程中,

函数是实现代码复用、简化逻辑和提高代码组织的重要工具。而函数的核心之一就是

参数传递机制,参数包括

实参(实际参数)和

形参(形式参数)。本文将详细讲解C语言中实参和形参的概念、它们的区别、关系以及使用方法,帮助你理解函数参数传递的原理和实际应用。我们还将探讨通过指针传递参数的方式,以便在函数中直接修改实参的值。

实参的概念

实参(实际参数)是在函数调用时传递给函数的值或表达式。它们是函数执行所需的具体数据。在调用函数时,实参被放置在函数名后面的括号内,实参可以是变量、常量,或者更复杂的表达式。

示例:实参传递

#include

#include

int main(void) {

int a;

scanf("%d", &a); // 从用户获取输入作为实参

printf("平方根是: %.2f\n", sqrt(a)); // 传递实参a给sqrt函数

return 0;

}

在上述示例中,a 是一个整数变量,它的值通过 scanf 函数从用户输入获取,之后作为实参传递给库函数 sqrt。sqrt(a) 的括号内的 a 就是实参,函数会使用这个实参进行计算。

实参的特点包括:

实参可以是常量、变量或表达式。实参在调用函数时被传递给函数的形参。

形参的概念

形参(形式参数)是在函数定义时声明的参数,它用于接收函数调用时传递的实际参数值。形参在函数定义时声明,并在函数体内作为局部变量使用,作用范围仅限于函数内部。

形参的语法结构

返回类型 函数名(形参列表) {

// 函数体

}

形参列表由多个形参组成,每个形参包括数据类型和参数名。形参在函数定义时不会有实际值,只有在函数调用时,实参的值才会传递给形参。

示例:形参接收实参

#include

void print_square_root(double num) {

printf("平方根是: %.2f\n", sqrt(num)); // num 是形参

}

int main() {

double x = 16.0;

print_square_root(x); // 实参x传递给形参num

return 0;

}

在这个例子中,print_square_root 函数有一个形参 num,在 main 函数调用 print_square_root 时,实参 x 被传递给形参 num,然后 num 在函数体中被用于计算平方根。

形参的特点包括:

形参在函数定义中声明,用于接收实参的值。形参在函数内部起作用,相当于局部变量。形参的初始值是通过函数调用时传递的实参值赋予的。

实参与形参的关系

实参和形参之间的关系可以理解为实参为形参提供值,并且这种值传递是在函数调用时发生的。当函数被调用时,实参的值被传递给形参,形参用于函数内部的计算。

实参与形参的传递过程

当调用函数时,实参的值被复制给形参。在函数体内,形参作为局部变量,参与函数的运算和逻辑处理。当函数执行完毕后,形参所占用的内存会被释放,不再保留任何数据。

示例:实参与形参的关系

#include

void add(int a, int b) {

int sum = a + b;

printf("两数之和是: %d\n", sum);

}

int main() {

int x = 5;

int y = 3;

add(x, y); // 实参 x 和 y 传递给函数 add 的形参 a 和 b

return 0;

}

在上述代码中:

变量 x 和 y 是实参,函数 add 的形参是 a 和 b。调用 add(x, y) 时,实参 x 和 y 的值分别被复制到形参 a 和 b,并在函数体内进行求和操作。

实参和形参的传递方式

在C语言中,函数的参数传递主要有两种方式:

值传递:传递的是实参的值,函数内部对形参的操作不会影响实参本身。指针传递:传递的是实参的地址,函数内部可以通过形参修改实参的值。

值传递

值传递是C语言中最常见的参数传递方式。通过值传递,函数内部修改形参的值并不会影响原始的实参,因为函数内部处理的是实参的副本。

示例:值传递

#include

void increment(int a) {

a = a + 1; // 修改的是形参 a 的值

}

int main() {

int x = 10;

increment(x); // 传递实参 x 的值

printf("x 的值是: %d\n", x); // 输出仍然是 10

return 0;

}

在这个例子中,虽然在 increment 函数中修改了形参 a 的值,但实参 x 并没有受到影响,仍然保持原始值 10。这是因为 x 的值是通过值传递的方式传递给 a,函数内部的修改只影响 a,不会修改 x。

指针传递

如果希望在函数内部修改实参的值,可以通过指针传递。通过传递实参的地址,函数内部可以通过形参直接访问并修改实参的值。

示例:指针传递

#include

void increment(int *a) {

*a = *a + 1; // 修改的是实参的值

}

int main() {

int x = 10;

increment(&x); // 传递实参 x 的地址

printf("x 的值是: %d\n", x); // 输出是 11

return 0;

}

在这个例子中,increment 函数接受一个指针 a,并通过解引用 *a 修改实参的值。由于传递的是 x 的地址,函数内部的修改会直接作用于实参 x,因此 x 的值变为 11。

示例讲解

示例1:计算两数之和(值传递)

#include

void sum(int a, int b) {

int result = a + b;

printf("两数之和是: %d\n", result);

}

int main() {

int x = 5, y = 10;

sum(x, y); // 传递值

return 0;

}

在这个例子中,函数 sum 接收两个参数 a 和 b,并输出它们的和。实参 x 和 y 的值被传递给形参 a 和 b。

示例2:交换两个数的值(指针传递)

#include

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); // 传递x和y的地址

printf("交换后:x = %d, y = %d\n", x, y);

return 0;

}

示例讲解

在上述示例中,swap 函数的目的是交换两个整数的值。我们通过指针传递实现了这一目标:

函数 swap 接受两个指针 a 和 b,它们分别指向 x 和 y 的地址。在 swap 函数内部,通过解引用 *a 和 *b 来访问并修改 x 和 y 的值。由于传递的是地址,swap 函数的操作会直接影响实参 x 和 y 的值。因此,交换操作完成后,x 和 y 的值已经改变。

程序的输出为:

交换前:x = 5, y = 10

交换后:x = 10, y = 5

这种通过指针传递的方式,允许函数修改调用者传递的实际数据,从而实现更灵活的操作。

扩展内容:指针与参数传递

C语言中,指针是处理内存地址的关键工具。使用指针传递参数不仅可以让函数修改实参的值,还可以在函数内部操作复杂的数据结构,如数组、结构体等。

传递数组

在C语言中,数组作为函数参数时会自动退化为指针。因此,传递数组实质上是传递数组的首地址,函数内部可以访问和修改数组的元素。

示例:传递数组

#include

void double_array(int *arr, int size) {

for (int i = 0; i < size; i++) {

arr[i] *= 2;

}

}

int main() {

int numbers[] = {1, 2, 3, 4, 5};

int size = sizeof(numbers) / sizeof(numbers[0]);

double_array(numbers, size); // 传递数组的首地址

printf("数组元素加倍后的结果:");

for (int i = 0; i < size; i++) {

printf("%d ", numbers[i]);

}

printf("\n");

return 0;

}

解释

在该示例中:

函数 double_array 通过指针访问数组,并将每个元素的值加倍。由于传递的是数组的地址,函数内部对数组元素的修改会直接影响到实参 numbers 数组。

输出结果为:

数组元素加倍后的结果:2 4 6 8 10

传递结构体指针

对于复杂数据结构如结构体,使用指针传递可以避免复制整个结构体数据,提高效率。

示例:传递结构体指针

#include

struct Point {

int x;

int y;

};

void move_point(struct Point *p, int dx, int dy) {

p->x += dx;

p->y += dy;

}

int main() {

struct Point p1 = {10, 20};

printf("移动前:x = %d, y = %d\n", p1.x, p1.y);

move_point(&p1, 5, -3); // 传递结构体指针

printf("移动后:x = %d, y = %d\n", p1.x, p1.y);

return 0;

}

在这个示例中,move_point 函数通过指针操作 Point 结构体,移动点的坐标。通过传递结构体的指针,我们可以直接修改结构体的内容。

程序的输出为:

移动前:x = 10, y = 20

移动后:x = 15, y = 17

指针与实参传递的总结

通过指针传递的方式,函数可以修改实参的值,或者操作复杂的数据结构。与值传递相比,指针传递效率更高,特别是在处理大型数据时,避免了不必要的内存复制。

总结

在C语言中,实参和形参是函数定义和调用时的核心概念。实参是实际传递给函数的值,形参则是在函数中接收实参的局部变量。实参和形参之间通过值传递或指针传递实现数据的传递。

值传递:函数内部修改形参的值不会影响实参。指针传递:通过传递地址,函数可以直接修改实参的值。

理解实参和形参的关系、以及它们的传递方式对于编写高效的C语言程序至关重要。特别是在处理数组、结构体等复杂数据结构时,使用指针传递可以提高程序的性能并优化内存使用。