←

C 语言程序设计 · C语言

函数定义与调用

函数定义与调用

结构化讲义

S1-7 · 5 个大纲考点讲义 · 已精编

练本节题目

S1-7.1

库函数的正确调用。

精编讲义 v1#

常考标准库函数与所属头文件速查表

必记

<math.h>

代表库函数
sqrt(x)、pow(x, y)、fabs(x)
参数与返回值类型
参数与返回值均为 double
高频考试要点
fabs(x) 求浮点数绝对值;求整数绝对值用 <stdlib.h> 的 abs(n)

<math.h>

代表库函数
ceil(x)、floor(x)
参数与返回值类型
返回 double
高频考试要点
ceil(3.2)=4.0(向上取整),floor(-3.2)=-4.0(向下取整)

<ctype.h>

代表库函数
isalpha(c)、isdigit(c)、isupper(c)、islower(c)、tolower(c)、toupper(c)
参数与返回值类型
int
高频考试要点
判断字母/数字/大小写及大小写转换;不记函数时可用 '0'<=c && c<='9' 替代

<stdlib.h>

代表库函数
rand()、srand(seed)、malloc(size)、free(p)、exit(0)
参数与返回值类型
见说明
高频考试要点
rand() % (b - a + 1) + a 生成 [a, b] 闭区间随机整数
随堂自测(3 题 · 共 49 道关联题)展开作答
填空2 分自测不计入学习进度

库函数____的原型说明是 char* strcpy(char*dest,char *src);

单选2 分自测不计入学习进度

下列函数功能为四舍五入计算的是

填空2 分自测不计入学习进度

有字符串 char s[] = "112", char t[] = "12", 则表达式 strcmp(s, t) > 0 的值为 ____。

S1-7.2

用户自定义函数的定义、类型与返回值。

精编讲义 v1#

函数定义语法、返回类型与原型声明规则

必记
  • 函数不能嵌套定义:C 语言中所有函数都是平行的,绝不允许在一个函数体内部定义另一个函数(但允许嵌套调用)。
  • 形参表独立声明:函数首部形参必须各自独立写出类型名,如 int max(int a, int b) 正确,写成 int max(int a, b) 编译报错!且函数首部圆括号后不能加分号(加分号是函数原型声明而非函数定义)。
  • 返回值类型看齐:函数返回值类型以函数首部定义的类型为准;若 return 表达式类型与函数返回类型不一致,系统自动将其转换为函数定义的类型(如 int f(void) { return 3.8; } 实际返回 3);无返回值函数必须声明为 void。
  • 先声明后调用:若自定义函数写在 main 函数之后,必须在调用前写出函数原型声明(如 int max(int, int);,声明中形参名可省略,末尾必有分号)。
随堂自测(3 题 · 共 206 道关联题)展开作答
填空2 分自测不计入学习进度

84 已有变量定义和函数调用语句:int x=57; isprime(x);函数isprime()用来判断一个整型数a是否为素数,若是素数,函数返回1,否则返回0。请编写isprime函数。

单选2 分自测不计入学习进度

以下正确的函数定义是()

填空2 分自测不计入学习进度

如果需要从被调函数返回一个函数值,被调函数中必须包含____语句。

S1-7.3

函数的正确调用、参数的值传递。

精编讲义 v1#

实参形参内存关系与单向值传递 vs 地址传递

必记
  • 形参生命周期:形式参数只有在函数被调用时才分配内存单元,调用结束立即释放;实参与形参占据不同的内存单元。
  • 单向值传递铁律:C 语言参数传递本质是实参向形参“单向传递值”。当传递普通变量值时,在函数内部修改形参的值,绝对不会改变主调函数中实参的值!
  • 地址传递(指针或数组名作参数):若要让被调函数修改主调函数中的变量,必须传递变量的地址(指针)或数组名(首地址),在被调函数中通过 *p 解引用或 arr[i] 下标修改原内存单元。

传值失败 vs 传址成功(交换两数经典对比)

必记
c
#include <stdio.h>

void swap_val(int x, int y) { /* 传值:仅交换形参副本,实参 a, b 丝毫未变 */
    int t = x; x = y; y = t;
}

void swap_ptr(int *x, int *y) { /* 传址:通过指针解引用修改实参内存 */
    int t = *x; *x = *y; *y = t;
}

int main(void) {
    int a = 3, b = 5;
    swap_val(a, b);
    printf("after swap_val: a=%d, b=%d\n", a, b); /* 仍为 3, 5 */
    swap_ptr(&a, &b);
    printf("after swap_ptr: a=%d, b=%d\n", a, b); /* 变为 5, 3 */
    return 0;
}
随堂自测(3 题 · 共 199 道关联题)展开作答
单选2 分自测不计入学习进度

19 若用数组名作为函数调用的实参,传递给形参的是______。

单选2 分自测不计入学习进度

有以下程序 int add (int a, int b){return(a+b); } main (){int k,a=5,b=10; f=add; ...} 则以下函数调用语句正确的是。

单选2 分自测不计入学习进度

被调函数调用结束后,返回到()

S1-7.4

函数的嵌套调用、递归调用。

精编讲义 v1#

递归调用两大要素与展开追踪方法

必记
  • 递归定义:函数直接或间接地在函数体内调用其自身称为递归调用。
  • 递归两大必备条件:① 必须有明确的递归终止条件(基例 / 边界条件),否则会导致栈溢出无限递归;② 每次递归调用都在向终止条件逼近(问题规模缩小)。
  • 做题追踪法:先顺着递推式一层层往下写到终止条件(“递”阶段),再从终止条件的值一层层往回代算(“归”阶段)。常见母题:阶乘 $n!$、斐波那契数列 $F(n)=F(n-1)+F(n-2)$、进制转换逆序打印。

递归求阶乘与逆序打印数字示例

重点
c
#include <stdio.h>

int fact(int n) {
    if (n <= 1) return 1;     /* 递归终止条件 */
    return n * fact(n - 1);   /* 递推关系 */
}

int main(void) {
    printf("5! = %d\n", fact(5)); /* 输出 120 */
    return 0;
}
随堂自测(3 题 · 共 61 道关联题)展开作答
单选2 分自测不计入学习进度

在 C 语言程序中,以下说法正确的是()。 A函数的定义可以嵌套,但函数的调用不可以嵌套 B 函数的定义不可以嵌套,但函数的调用可以嵌套 C函数的定义和函数的调用都不可以嵌套 D函数的定义和函数的调用都可以嵌套

判断1 分自测不计入学习进度

如果计算机堆栈允许,函数可以无限嵌套。( )

单选2 分自测不计入学习进度

下列的结论中只有()是正确的。

S1-7.5

局部变量与全局变量。

精编讲义 v1#

变量作用域与四种存储类别(auto / static / register / extern)对比

必记

自动局部变量 auto(默认省略)

存储区域
动态存储区(栈区)
生命周期
进入函数时创建,函数返回即销毁
未显式赋初值时的默认值与高频考点
未初始化时值为不确定的随机数;每次进入函数都会重新初始化

静态局部变量 static

存储区域
静态存储区
生命周期
整个程序运行期间持续存在,不随函数返回销毁
未显式赋初值时的默认值与高频考点
编译时自动赋初值 0(或 '\0');初始化语句只在第一次调用时生效一次,后续调用保留上次结束时的值!

全局变量(外部变量)

存储区域
静态存储区
生命周期
整个程序运行期间
未显式赋初值时的默认值与高频考点
自动赋初值 0;当局部变量与全局变量同名时,在局部范围内局部变量优先(遮蔽全局变量)

外部声明 extern vs 静态全局 static

存储区域
静态存储区
生命周期
整个程序运行期间
未显式赋初值时的默认值与高频考点
extern 仅作外部变量声明(不分配内存)以扩展作用域;全局变量加 static 则限制仅在本源文件内可见

static 静态局部变量保留上一次值必考真题

必记
c
#include <stdio.h>

int fun(int a) {
    static int k = 1;         /* 仅第一次调用时初始化为 1,之后保留上次结果 */
    int m = 1;                /* auto 局部变量,每次调用都重新置 1 */
    k += a;
    m += a;
    return k + m;
}

int main(void) {
    int s1 = fun(2);          /* 第1次:k=3, m=3, 返回 6 */
    int s2 = fun(2);          /* 第2次:k在3基础上+2得5, m=3, 返回 8 */
    printf("s1=%d, s2=%d\n", s1, s2);
    return 0;
}

综合程序设计安全规范(对应复核项 30542)

重点

注意事项

在编写文件读写与结构体数组排序程序(如学生成绩文件排序 30542)时:① 数组大小需与循环边界严格一致,防止 a[N] 越界;② 打开文件 fopen 后应在读取/写入循环结束后只调用一次 fclose(fp),切忌在循环内重复关闭文件句柄。

随堂自测(3 题 · 共 133 道关联题)展开作答
单选2 分自测不计入学习进度

以下与存储类别有关的四组说明符中,全部属于静态类的一组是____。

判断1 分自测不计入学习进度

一个函数中定义了一个静态变量。当该函数每一次调用时,这个静态变量都会被初始化一次。()

综合6 分自测不计入学习进度

有函数 void fun() { static int a; int b;},则 a 和 b 的值分别为()。