C 语言编程教程

C 语言 - 首页

C 语言基础

C 语言 - 概述 C 语言 - 特性 C 语言 - 发展历史 C 语言 - 环境设置 C 语言 - 程序结构 C 语言 - Hello World C - 编译过程 C - 注释 C - 标记 C - 关键字 C - 标识符 C - 用户输入 C - 基本语法 C - 数据类型 C - 变量 C - 整数提升 C - 类型转换 C - 类型转换 C - 布尔值

C 语言中的常量和文字

C - 常量 C - 字面量 C - 转义序列 C - 格式说明符

C 语言中的运算符

C - 运算符 C - 算术运算符 C - 关系运算符 C - 逻辑运算符 C - 位运算符 C - 赋值运算符 C - 一元运算符 C - 递增和递减运算符 C - 三元运算符 C - sizeof 运算符 C - 运算符优先级 C - 其他运算符

C 语言中的决策

C - 决策 C - if 语句 C - if...else 语句 C - 嵌套 if 语句 C - switch 语句 C - 嵌套 switch 语句

C 语言中的循环

C - 循环 C - While 循环 C - For 循环 C - Do...while 循环 C - 嵌套循环 C - 无限循环 C - Break 语句 C - Continue 语句 C - goto 语句

C 语言中的函数

C - 函数 C - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 C - 递归

C 语言中的作用域规则

C - 作用域规则 C - 静态变量 C - 全局变量

C 语言中的数组

C - 数组 C - 数组的属性 C - 多维数组 C - 将数组传递给函数 C - 从函数返回数组 C - 可变长度数组

C 语言中的指针

C - 指针 C - 指针和数组 C - 指针的应用 C - 指针运算 C - 指针数组 C - 指向指针的指针 C - 将指针传递给函数 C - 从函数返回指针 C - 函数指针 C - 指向数组的指针 C - 指向结构体的指针 C - 指针链 C - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 C - 预处理器操作符 C - 宏 C - 头文件

C 语言中的内存管理

C - 内存管理 C - 内存地址 C - 存储类

C 其他主题

C - 错误处理 C - 可变参数 C - 命令执行 C - 数学函数 C - static 静态关键字 C - 随机数生成 C - 命令行参数

C 语言编程资源

C语言问题与解答答案 C语言快速指南 C语言速查表 C语言实用资源 C语言讨论


C 语言中的用户定义函数

C 语言中的函数是一段有组织的、可重用的代码块,用于执行单个相关操作。任何 C 语言程序中,都有一个或多个函数,这些函数分为库函数和用户定义函数。

C 语言中有两种类型的函数 -

  • 库函数
  • 用户定义函数

任何 C 语言编译器(例如 GCC 编译器、Clang、MSVC 编译器等)都附带许多预编译的头文件(stdio.hmath.h 等),每个头文件都包含一个或多个预定义的库函数,例如 printf()scanf()pow()sqrt() 等。要使用库函数,必须使用 #include 指令提供相应的头文件。

但是,如果您找不到合适的库函数来满足您的目的,则可以为程序定义自定义函数。通常,我们会在 C 程序中找到一个 main() 函数。显然,main() 函数是用户定义函数,因为它包含用户提供的指令。当然,它可以调用其他库或用户定义函数。

C 语言中的用户定义函数是什么?

用户定义函数是由用户定义的函数,用于执行特定任务,从而实现代码的可重用性和模块化。创建和使用用户定义函数无需使用任何内置库。这些函数可以在同一程序中创建,也可以在用户定义的头文件中创建。

创建用户定义函数

要创建用户定义函数,首先需要了解函数的用途,即您希望该函数执行什么操作?

要创建用户定义函数,您需要了解函数的以下三个部分:

  • 函数声明
  • 函数定义
  • 函数调用

用户定义函数的声明

在 C 语言中,任何函数都必须提供原型声明。库函数的原型位于相应的头文件中。

对于用户定义函数,其原型位于当前程序中。函数的定义与其原型声明应该匹配。

语法

如果您要定义一个名为 add() 的函数,该函数执行两个整数参数的加法运算并返回整数值,则函数声明应如下:

int add(int, int);

用户定义函数的定义

函数的定义与其原型声明应该匹配。该定义由与声明匹配的函数头和函数体组成。

语法

return_type function_name(arg1, arg2, ...){

   // 函数主体;

   return val;

}

示例

使用此模板,您可以编写用户定义函数 add(),如下所示 -

int add(int a, int b){
   int c;
   c = a + b;
   return c;
}

请注意,在 C 程序中,用户定义函数的定义顺序并不重要。但是,必须在调用函数之前声明其原型。

在程序中,main() 函数始终是入口点,无论它是否是第一个函数。我们无需提供 main() 函数的原型声明。

调用用户定义函数

要调用函数,您应该使用符合函数原型声明的语句。如果函数定义为接收一定数量的参数,则必须传递相同数量和类型的参数才能调用该函数。

示例

以下语句调用我们上面定义的 add() 函数 -

int result = add(10, 20);

用户定义函数示例

在此示例中,我们创建两个用户定义函数 add()sub(),用于计算给定数字的加法和减法。

// C 程序演示用户定义函数示例
// #include <stdio.h>

// 函数声明
int add(int, int);
int sub(int, int);

// 函数定义
int add(int a, int b) {
  return (a + b);
}

int sub(int a, int b) {
  return (a - b);
}

int main() {
    // 声明两个整数变量来存储数字
    // 以及用于存储结果的 result 变量
    int num1 = 36, num2 = 24;
    int res_add, res_sub;
    
    // 调用函数
    res_add = add(num1, num2);
    res_sub = sub(num1, num2);
    
    // 打印结果
    printf("Addition is : %d
", res_add);
  printf("Subtraction is : %d
", res_sub);

  return 0;
}

Addition is : 60
Subtraction is : 12

用户定义函数中的形式参数和实际参数

当函数定义时带有参数,函数名称前面括号中的参数称为形式参数。在上例中,函数定义了"int a"和"int b"两个参数;它们是形式参数。

当函数被调用时,传递给它的参数称为实际参数。在下面的例子中,变量"x"和"y"是实际参数。

int x = 10, y = 20;
int result = add(x, y);

用户定义函数可以定义为使用任何类型的变量作为形式参数。它包括基本类型(int、float、char)、数组、指针或结构体/联合体类型变量。

函数应该向调用环境返回一个值。默认情况下,函数的返回类型为int类型。但是,它可以返回任何数据类型 - 基本类型、数组、指针、结构体以及指针。您甚至可以定义一个返回void类型的函数。

示例

如果函数的前向声明和定义中实际参数和形式参数的数量或类型,或者返回类型不匹配,则编译器会报告错误。

请看下面的示例 -

#include <stdio.h>

float divide (int, int);

int main(){

   int x = 15, y = 5;

   float z = divide (x, y);
   
   printf("%f", z);

   return 0;
}

int divide (int a, int b){

   int c = a/b;

   return c;
}

输出

在上面的代码中,divide() 函数的声明与其定义不匹配,因此编译器显示以下错误 -

error: conflicting types for 'divide'

在 C 语言中,任何函数都可以调用任何其他函数,调用次数不限。函数也可以调用自身。这种自调用函数称为递归函数

以下程序从 main() 函数内部调用 main() 函数 -

#include <stdio.h>

int main(){

   printf("Hello");

   main();

   return 0;
}

程序执行时会陷入无限循环。实际应用中,必须使用递归才能使程序最终终止。