函数简单的说,就是封装了一些语句的代码块,可以被重复调用
1.函数定义
示例:
int add(int a, int b) {
return a + b;
}
以上就是一个函数的具体定义
定义一个函数时,需要注意以下几点:
- 返回类型:函数必须指定一个返回类型(如add 前的int),return 语句不能少;如果函数不返回任何值,则使用
void,没有return语句,如下函数:
void print_hello() { printf("Hello, world!\n"); }
- 函数名:函数名(add)应符合标识符的命名规则,通常使用小写字母,多个单词之间用下划线分隔
- 参数列表:参数列表中可以包含零个(如print_hello函数)或多个参数,每个参数需要指定类型和名称(int a, int b)
- 函数体:函数体用大括号
{}
包围,包含具体的代码实现
2.函数声明
示例:
int add(int, int);
函数声明(也称为函数原型)告诉编译器函数的名称、返回类型和参数类型,但不包含具体的实现。函数声明通常放在头文件中,或者在源文件的顶部。
注意事项:
- 返回类型:与函数定义一致。
- 函数名:与函数定义一致。
- 参数列表:参数列表只需指定类型,不需要名称(但也可以包含名称)。
C语言是顺序执行的语言,函数再使用之前,必须先定义或者声明,也就是说可以有两种情况
2.1.先定义,后调用
#include <stdio.h>
int add(int a, int b) // 定义函数
{
return a + b;
}
int main()
{
int x = 5, y = 10;
int z = add(x, y); // 调用函数
printf("The sum of %d and %d is %d\n", x, y, z);
return 0;
}
2.2.先声明,接着调用,最后定义
#include <stdio.h>
int add(int, int); //声明函数
int main()
{
int x = 5, y = 10;
int z = add(x, y); //调用函数
printf("The sum of %d and %d is %d\n", x, y, z);
return 0;
}
int add(int a, int b) //定义函数
{
return a + b;
}
在实际的工作中,我们经常把函数的声明放到一个头文件中,函数的定义放到一个源文件或者库文件中,这样就可以隐藏了代码的实现细节,从而实现了代码的封装、复用和模块化
3.main函数
在 C 语言中,程序的执行入口是 main
函数。每个 C 程序都必须有一个 main
函数,程序的执行从main函数开始的,如上面的例子
4.函数参数
4.1参数类型:
形式参数(Formal Parameters)
形式参数是在函数定义中声明的参数。它们在函数体内用于接收调用者传递的实际参数的值或地址。形式参数在函数调用时被创建,并在函数返回时被销毁。
示例:
void add(int a, int b) { // a 和 b 是形式参数
printf("Sum: %d\n", a + b);
}
实际参数(Actual Parameters)
实际参数是在函数调用时传递给函数的参数。它们可以是常量、变量或表达式。实际参数的值或地址会被复制给形式参数。
示例:
int main() {
int x = 5, y = 10;
add(x, y); // x 和 y 是实际参数
return 0;
}
4.2参数调用方式
传值调用(Call by Value)
传值调用是 C 语言中最常见的参数传递方式。在这种方式下,函数调用时会将实际参数的值复制给形式参数
函数内部对形式参数的修改不会影响实际参数
示例:
#include <stdio.h>
void increment(int a) { // 参数不为指针类型
a++;
printf("Inside function: a = %d\n", a); // 输出: Inside function: a = 6
}
int main() {
int x = 5;
increment(x);
printf("Outside function: x = %d\n", x); // 输出: Outside function: x = 5
return 0;
}
在这个例子中,increment
函数接收一个整数参数 a
,并对其进行自增操作。然而,这个操作只影响形式参数 a
,不会改变外部的实际参数 x
的值
传址调用(Call by Reference)
传址调用是通过传递指针来实现的
在定义函数的时候,参数必须是指针类型
在这种方式下,函数调用时会将实际参数的地址(指针)传递给形式参数。函数内部通过指针访问和修改实际参数的值
示例:
#include <stdio.h>
void increment(int *a) { // 参数必须为指针类型
(*a)++;
printf("Inside function: *a = %d\n", *a); // 输出: Inside function: *a = 6
}
int main() {
int x = 5;
increment(&x);
printf("Outside function: x = %d\n", x); // 输出: Outside function: x = 6
return 0;
}
在这个例子中,increment
函数接收一个指向整数的指针 a
,并通过解引用指针来修改实际参数 x
的值。因此,函数内部的修改会影响到外部的变量 x
总结
- 传值调用:函数调用时将实际参数的值复制给形式参数,函数内部对形式参数的修改不会影响实际参数
- 传址调用:函数调用时将实际参数的地址传递给形式参数,函数内部通过指针访问和修改实际参数的值
5.函数指针和指针函数的区别
函数指针和指针函数是 C 语言中两个容易混淆的概念,它们在定义和用途上有明显的区别。
函数指针(Function Pointer)
函数指针是指向函数的指针变量。它存储的是函数的地址,可以通过函数指针调用函数。
定义方式:
返回类型 (*指针变量名)(参数类型列表);
示例:
int (*funcPtr)(int, int); // 定义一个函数指针,指向返回类型为 int,参数为两个 int 的函数
示例代码:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
int (*funcPtr)(int, int) = add; // 将函数指针指向 add 函数
int result = funcPtr(3, 4); // 通过函数指针调用 add 函数
printf("Result: %d\n", result); // 输出: Result: 7
return 0;
}
用途:
- 可以在运行时动态地选择和调用不同的函数。在运行时动态地选择和调用不同的函数
在下面这个例子中,我们将定义几个不同的数学运算函数,并通过函数指针在运行时选择和调用不同的函数
#include <stdio.h> // 定义加法函数 int add(int a, int b) { return a + b; } // 定义减法函数 int subtract(int a, int b) { return a - b; } // 定义乘法函数 int multiply(int a, int b) { return a * b; } // 定义一个函数指针类型 typedef int (*MathFunc)(int, int); // 根据操作符选择相应的函数 MathFunc getOperation(char op) { switch (op) { case '+': return add; case '-': return subtract; case '*': return multiply; default: return NULL; // 无效操作符 } } int main() { char op; int a, b; printf("Enter operation (+, -, *): "); scanf(" %c", &op); printf("Enter two numbers: "); scanf("%d %d", &a, &b); MathFunc func = getOperation(op); // 获取相应的函数指针 if (func != NULL) { int result = func(a, b); // 调用相应的函数 printf("Result: %d\n", result); } else { printf("Invalid operation\n"); } return 0; }
在这个例子中,我们定义了三个数学运算函数 add
、subtract
和 multiply
,并通过 getOperation
函数根据用户输入的操作符返回相应的函数指针。在 main
函数中,我们根据用户输入的操作符动态地选择和调用相应的函数。
- 常用于回调函数、事件处理等场景
指针函数(Pointer Function)
指针函数是返回值为指针的函数。它是一个函数,其返回类型是一个指针。
定义方式:
返回类型 *函数名(参数类型列表);
示例:
int* getPointer(int value); // 定义一个返回 int 指针的函数
用途:
- 返回动态分配的内存地址。
- 返回数组或其他数据结构的指针。
示例代码:
#include <stdio.h>
#include <stdlib.h>
int* getPointer(int value) {
int* ptr = (int*)malloc(sizeof(int)); // 动态分配内存
*ptr = value; // 将值存储在动态分配的内存中
return ptr; // 返回指针
}
int main() {
int* ptr = getPointer(10); // 调用指针函数,获取指向整数的指针
printf("Value: %d\n", *ptr); // 输出: Value: 10
free(ptr); // 释放动态分配的内存
ptr = NULL; // 置空指针
return 0;
}
总结
- 函数指针:是指向函数的指针变量,用于存储函数的地址,可以通过函数指针调用函数。
- 指针函数:是返回值为指针的函数,用于返回指针类型的数据。
理解这两个概念的区别对于掌握 C 语言的指针和函数的使用非常重要