7022 字
35 分钟
C语言考查笔记
2023-11-23
C
NOTE

考查目标:

  1. 掌握 C 语言程序结构
  2. 掌握 C 语言的基本数据类型及数据运算
  3. 掌握基本语句的使用
  4. 掌握选择结构编程
  5. 掌握循环结构编程
  6. 掌握数组存储与处理批量数据.
  7. 了解模块化程序设计思想, 学会使用函数进行简单编程.

1、C 语言程序的结构#

1.1 程序的构成, main 函数和其他函数#

  • 程序的构成: 一个 C 语言源程序由一个或多个源文件组成. 每个源文件可以由一个或多个函数组成.
  • 主函数 (main 函数): 一个源程序有且只能有一个 main 函数, 它是主函数. 程序执行从 main 开始, 并在 main 中结束.
  • 函数组成: 函数由两部分组成: 声明 (Declaration) 和定义 (Definition, 即函数体, 要执行的代码).

示例代码: main 函数结构

# include <stdio.h> // 预处理命令, 载入头文件
int main() // 主函数
{
printf("Hello World!"); // 标准输出
return 0;
}

1.2 头文件, 数据说明, 程序注释#

  • 头文件: 预处理命令 (以 # 开头) 通常应放在源文件或源程序的最前面.
    • 例如, 使用 #include <stdio.h> 来获取标准输入输出函数.
    • 系统库中的头文件使用尖括号 < > 引用; 本地目录中的头文件使用双引号 "" 引用.
  • 数据说明(变量定义):
    • 变量在使用前必须声明. 声明方式为 类型标识符 变量名列表;.
    • 可以在声明时同时初始化变量.
  • 程序注释:
    • 单行注释: 使用 //.
    • 多行注释(段注释符): 使用 /* ... */.
    • 注意事项: 多行注释不能嵌套, 否则会导致编译错误.

示例代码: 变量定义与注释

#include <stdio.h> // 包含头文件
// 这是一个单行注释
/*
多行注释:
用于注释跨多行的内容
*/
const int MAX_LENGTH = 100; // 符号常量声明
int main()
{
int myNum = 15; // 定义并初始化变量 myNum
float myFloatNum; // 声明变量
myFloatNum = 5.99; // 初始化变量
return 0;
}

1.3 源程序的书写格式#

  • 语句结束符: 每条语句以分号 ; 结尾. 但预处理命令、函数头和右花括号 } 之后不需要加分号 (结构除外).
  • 大小写: C 语言区分大小写.
  • 书写规范: 常用锯齿形书写格式. 建议花括号 {} 对齐, 一行写一个语句, 使用 TAB 缩进, 有合适的空行, 以提升程序可读性.

2、数据类型及其运算#

2.1 C 语言的基本数据类型及定义方法#

C 语言的数据类型可分为基本数据类型和派生 (扩展) 数据类型.

  • 基本数据类型:
    • 整型: int, short, long.
      • int: 整型, 4 个字节 (32 位), 范围约为 -2,147,483,648 到 2,147,483,647.
      • short: 短整型, 2 个字节 (16 位), 范围约为 -32,768 到 32,767.
      • long: 长整型, 4 个字节 (32 位), 范围约为 -2,147,483,648 到 2,147,483,647.
    • 实型(浮点型): float (单精度浮点型), double (双精度浮点型), long double.
      • float: 4 个字节 (32 位), 精度约为 7 位十进制数.
      • double: 8 个字节 (64 位), 精度约为 15-16 位十进制数.
      • long double: 10、12 或 16 个字节, 具体取决于编译器, 精度更高.
    • 字符型: char.
      • char: 1 个字节 (8 位), 用于存储字符 (如字母、数字、标点符号等).
      • 字符型变量可以直接赋值字符常量 (如 'A', '1', '!'), 也可以赋值对应的 ASCII 码值 (如 65, 49, 33).
    • 布尔型: _Bool (0 表示 false, 1 表示 true).
      • _Bool 类型占用 1 个字节 (8 位), 只能存储 01.
      • 布尔型变量通常用于条件判断和循环控制.
  • 派生/扩展类型: 数组、指针、枚举 (enum), 结构 (struct), 联合 (union) 等.
  • 字符串: 不是一种独立的数据类型, 通过字符数组或字符指针来实现. 以 \0 (空字符) 为结束标志.

示例代码: 基本数据类型定义

// 定义并初始化整数变量
int myNum = 5;
// 定义并初始化浮点数变量
float myFloatNum = 5.99;
// 定义并初始化字符变量
char myLetter = 'D';
// 定义双精度浮点数
double myDouble = 3.2325467;
// 定义布尔型变量
_Bool myBool = 1;
// 定义并初始化字符串变量
char myString[] = "Hello World!";
// 定义并初始化字符数组变量
char myCharArray[] = {'H', 'e', 'l', 'l', 'o', '\0'};
// 定义并初始化指针变量
char *myPointer = "Hello World!";

2.2 C 语言运算符的种类、运算优先级和结合性#

C 语言运算符的种类包括:

  • 算术运算符: + (加), - (减), * (乘), / (除), % (取模), ++ (增量), -- (乘量/减量).
  • 赋值运算符: = (赋值), +=, -=, *=, /=, %= 等. (a += b → a = a + b)
    • 自增运算符前置与后置的区别:
    • ++-- 运算符放在变量前面 (如 ++i, --i) 称为前置, 先进行自增/自减操作, 再使用变量的值
    • ++-- 运算符放在变量后面 (如 i++, i--) 称为后置, 先使用变量的当前值, 再进行自增/自减操作
  • 关系运算符(比较运算符): == (等于), != (不等于), > (大于), < (小于), >= (大于或等于), <= (小于或等于).
  • 逻辑运算符: && (逻辑与), || (逻辑或), ! (逻辑非). 优先级为 ! 优于 && 优于 ||.
  • 条件运算符: ? :, 是 C 语言中唯一的三目运算符.
  • 位运算符: & (按位与), | (按位或), ^ (异或), ~ (取反), << (左移), >> (右移).
  • 指针运算符: * (取内容/解引用), & (取地址).
  • 求字节数运算符: sizeof.

示例代码: 重要运算符的使用

// 算术运算符和前置/后置
int a = 5, b = 3;
int sum = a + b; // 加法
// 前置和后置自增
int x = 10;
int y = ++x; // x 先自增为 11, 然后赋值给 y, y = 11
int z = x++; // x 的当前值 11 赋值给 z, 然后 x 自增为 12, z = 11
// 关系运算符
int result1 = (a > b); // result1 = 1 (true)
int result2 = (a == b); // result2 = 0 (false)
// 逻辑运算符
// 可以对表达式、单个数字或变量进行逻辑运算
int result3 = (a > 0 && b < 10); // result3 = 1 (true)
int result4 = (a < 0 || b > 10); // result4 = 0 (false)
int result5 = !(a == b); // result5 = 1 (true)
int result6 = !a || b; // result6 = 1 (true)
// 条件运算符
int max = (a > b) ? a : b; // 条件为真返回 a, max = 5
// 位运算符
int bitwise_and = a & b; // 按位与: 对应位都为 1 时结果为 1, 否则为 0, 这里 5 & 3 = 1 (二进制: 101 & 011 = 001)
int bitwise_or = a | b; // 按位或: 对应位有一个为 1 时结果为 1, 否则为 0, 这里 5 | 3 = 7 (二进制: 101 | 011 = 111)
int left_shift = a << 1; // 左移 1 位: 相当于乘以 2, 例如 5 << 1 = 10 (二进制: 101 << 1 = 1010)
// 指针运算符
int *ptr = &a; // ptr 是一个指针变量, 它存储了变量 a 的内存地址
int value = *ptr; // 通过指针获取 a 的值, value = 5
// sizeof 运算符
int size = sizeof(int); // size = 4

2.3 不同类型数据间的转换与运算#

  • 自动转换(隐式转换):
    • 不同类型的数据进行运算时, 需要先转换成同一数据类型, 然后再进行运算.
    • 转换按数据长度增加的方向进行, 以尽可能保证精度不降低.
    • 例: char 型数据和 short 型数据进行运算时, 需转换成 int 型.
    • 转换方向示例 (部分): char --> short --> int --> unsigned --> long --> unsigned long --> double <-- float.
    • 浮点型转整型: 直接丢掉小数部分.
  • 强制转换(显式转换):
    • 语法: (类型标识符)表达式.
    • 类型转换是临时性的, 不会改变变量本身的数据类型.
    • 运算过程中, 自动类型提升: 低精度数据类型向高精度数据类型转换.

示例代码: 类型转换

int a = 2, b = 5;
double x, y, z;
x = b / a; // 隐式转换: b/a 先进行整型除法 (2), 然后赋值给 double 型 x, x = 2.0
y = (double)b / a; // 强制转换: 先将 b 转化为 double 型 (5.0), 然后进行浮点数除法, y = 2.5
z = (double)(b / a); // 强制转换: 先计算整型除法 (2), 然后将结果 2 转化为 double 型, z = 2.0

2.4 C 语言表达式类型和求值规则#

  • 赋值表达式: 将右侧的值赋给左侧的变量, 例如 x = 5. 赋值号具有结合性, 如 x=y=3 等价于 y=3; x=y;.
  • 算术表达式: 使用算术运算符连接常量和变量, 例如 sum = x + y.
  • 关系表达式: 使用关系运算符进行比较, 返回 1 (真) 或 0 (假).
  • 逻辑表达式: 使用逻辑运算符连接表达式.
    • 短路求值: 对于 &&, 如果左侧为假, 则不再计算右侧; 对于 ||, 如果左侧为真, 则不再计算右侧.
  • 条件表达式(三元运算符):
    • 语法: (条件表达式) ? 表达式1 : 表达式2.
    • 求值规则: 如果条件表达式为真, 返回表达式 1 的值, 否则返回表达式 2 的值.
  • 逗号表达式:
    • 语法: 表达式1, 表达式2.
    • 求值规则: 先计算表达式 1, 再计算表达式 2, 并将表达式 2 的值作为整个表达式的结果.

示例代码: 条件表达式(三元运算符)

int time = 20;
int main() {
(time < 18) ? printf("再会!") : printf("晚上好!"); // 输出 -> "晚上好!"
return 0;
}

示例代码: 逗号表达式

int a = 2, b;
int main() {
a = 3 * 5, a + 10; // a=15, 整个表达式结果是 15+10=25, 但后面的 a+10 未赋值, 丢弃
b = (3 * 5, a + 10); // 使用括号, 3*5=15 (未赋值, 丢弃), 然后 a+10=25, b=25
printf("a = %d, b = %d\n", a, b);
return 0;
}

3、基本语句#

3.1 表达式语句, 空语句, 复合语句#

  • 表达式语句: 由表达式 (如赋值表达式、函数调用) 后跟分号组成.
  • 空语句: 只有分号 ;.
  • 复合语句: 将多个语句用花括号 {} 括起来组成的一个语句. 通常用于 if, for, while 等结构中, 作为循环体或条件体.

3.2 输入输出函数的调用, 正确输入数据并正确设计输出格式#

  • 输出函数的调用: 使用 printf().
    • 语法: printf("格式控制字符串", 输出变量列表);.
  • 输入函数的调用: 使用 scanf().
    • 语法: scanf("格式控制字符串", 输入变量地址列表);. 注意最后一个参数是变量的地址列表.
  • 格式说明符 (作用): 充当变量输出时的占位符, 用于指定变量的输出格式.
    • %d%i: int 整数 (10 进制).
    • %u: 无符号十进制整数
    • %f: float 浮点数 (小数形式).
    • %.2f: 浮点数保留2位小数
    • %lf: double 高精度浮点数据.
    • %c: char 字符.
    • %s: 字符串.
    • %.5s: 字符串最多输出5个字符
  • 输出格式设计(宽度控制):
    • 使用 %md%-md 控制输出宽度 m.
      • %md: 最少占 m 个字符宽度, 默认右对齐.
      • %-md: 最少占 m 个字符宽度, 左对齐.

示例代码: 输入输出及格式控制

#include <stdio.h>
int main()
{
int myNum;
float f = 5.99;
// 输出
printf("Number = %d\n", (int)f); // 输出整数, 5
printf("Value = %.2f\n", f); // 输出浮点数, 保留两位小数, 5.99
// 输出格式控制(左对齐, 宽度为 9)
int a1 = 20;
printf("%-9d\n", a1); // 输出 20, 左对齐, 宽度为 9
// 输入
printf("请输入一个数字: \n");
scanf("%d", &myNum); // 获取并保存用户输入的号码, 需要使用 & 引用运算符
printf("您输入的数字: %d\n", myNum);
return 0;
}

4、选择结构程序设计#

4.1 用 if 语句实现选择结构#

  • if 语句: 用于根据条件执行代码块.
  • if…else 语句: 在 if 条件不满足时执行 else 代码块.
  • else if 语句: 用于检查多个条件.

示例代码: if-else if-else 结构

int time = 22;
if (time < 10) {
printf("早上好!");
} else if (time < 20) {
printf("再会!");
} else {
printf("晚上好!"); // 输出 -> "晚上好!"
}

4.2 用 switch 语句实现多分支选择结构#

  • switch 语句: 根据表达式的值跳转到匹配的 case 标签.
  • 表达式类型: switch 表达式可以是整型、字符型和枚举型.
  • break 语句: 匹配到 case 后执行相应代码, 并通过 break 跳出 switch.
  • default 语句: 如果没有匹配到任何 case, 则执行 default 语句 (如果存在). default 不是必需的.
  • 贯穿现象: 如果没有 break, 程序会继续执行下一个 case 的代码.

示例代码: switch 结构

int day = 4;
switch (day) {
case 3:
printf("周三");
break;
case 4:
printf("周四"); // 匹配到 case 4
break; // 跳出 switch
default:
printf("期待周末");
}
// 输出 -> "周四"

4.3 选择结构的嵌套#

  • if 语句可以嵌套.
  • 嵌套时, 每一层 if 都要和 else 配套, 若没有 else, 则需要将该层 if 语句用 {} 括起来.

示例代码: if 嵌套

int time = 10;
if (time > 8) {
// 嵌套一个 if
if (time < 12) {
printf("中午好!"); // 输出 -> "中午好!"
}
}

5、循环结构程序设计#

5.1 for 循环结构#

  • for 循环结构包含三个表达式: 初始化语句 (表达式 1, 只执行一次), 循环条件表达式 (表达式 2, 每次循环前检查), 调整操作 (表达式 3, 循环体执行后执行).
  • 当条件表达式 (表达式 2) 为假时, for 循环结束.
  • 三个表达式都不是必须的, 但分号不能省略. 如果表达式 2 为空, 则表示无限循环.

示例代码: for 循环

int i;
for (i = 0; i < 5; i++) { // i=0 (初始化), i<5 (循环条件), i++ (调整操作)
printf("%d\n", i);
}
// 输出 -> 0 1 2 3 4
// 省略表达式1(初始化在外部进行)
int i = 0;
for (; i < 5; i++) {
printf("%d\n", i);
}
// 省略表达式3(调整操作在循环体内进行)
for (i = 0; i < 5;) {
printf("%d\n", i);
i++;
}
// 省略表达式2(无限循环)
for (i = 0; ; i++) {
if (i >= 5) break; // 需要用break来跳出循环
printf("%d\n", i);
}
// 三个都省略(必须有办法跳出循环)
for (;;) {
printf("无限循环");
break; // 必须有退出条件
}

5.2 while 和 do-while 循环结构#

特征while 循环do-while 循环
控制类型入口控制循环 (Entry-Controlled)出口控制循环 (Exit-Controlled)
条件检查在循环体执行检查在循环体执行检查
执行保证可能执行 0 次或多次至少执行 1
语法结尾} 后无分号while(条件)分号

示例代码: while 循环

int i = 0;
while (i < 5) {
printf("%d\n", i); // 初始条件为假时,循环体不执行
i++;
}
// 输出 -> 0 1 2 3 4

示例代码: do-while 循环

int i = 0;
do {
printf("%d\n", i);
i++;
} while (i < 5); // ← 注意:分号不能省略,这是必须的
// 输出 -> 0 1 2 3 4

5.3 continue 语句和 break 语句#

  • break 语句: 跳出当前 循环switch 语句, 执行后续代码.
  • continue 语句: 跳过当前循环的剩余语句, 直接进入下一次循环.
  • 通常与 if 语句配合使用.

示例代码: break 语句

int i;
for (i = 0; i < 10; i++) {
if (i == 4) {
break; // 当 i=4 时跳出循环
}
printf("%d\n", i);
}
// 输出 -> 0 1 2 3

示例代码: continue 语句

int i;
for (i = 0; i < 10; i++) {
if (i == 4) {
continue; // 当 i=4 时跳过本次循环的剩余部分 (即跳过 printf)
}
printf("%d\n", i);
}
// 输出 -> 0 1 2 3 5 6 7 8 9

5.4 循环的嵌套#

  • 循环可以嵌套.
  • 嵌套循环的核心在于执行顺序, 外部循环每执行一次, 内部循环都要完整地执行完所有轮次.
  • 总的循环体执行次数是: 外循环次数 × 内循环次数.

示例代码: 循环嵌套 (遍历二维数组)

int N = 5;
// 假设 A 是一个 N x N 的二维数组, 外部循环控制行, 内部循环控制列
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
printf("%d ", A[i][j]); // 循环体语句, 访问 A[i][j]
}
}

示例代码: 循环嵌套 (九九乘法表)

for (int i = 1; i <= 9; i++) { // 外层循环控制行
for (int j = 1; j <= i; j++) { // 内层循环控制列
printf("%d*%d=%-2d ", j, i, i*j); // %-2d 表示左对齐,占两个宽度
}
printf("");
}

6、数组的定义和引用#

6.1 一维数组的定义、初始化和数组元素的引用#

  • 定义: 一维数组的声明格式为 类型标识符 数组名[n], 其中 n 是一个正整数常量, 表示数组的长度. (声明时指定长度不可省略, 但初始化时可省略长度由编译器自动推断.)
  • 引用: 通过 数组名[k] 引用数组元素, 下标 k 的合法取值范围是从 0n-1.
  • 初始化: 可以在声明时同时赋初值.
    • 当在定义时对所有元素都进行初始化时, 可以省略数组长度 [n], 编译器会根据初始化列表的元素个数自动确定数组长度.
    • 可以只初始化部分元素, 未被初始化的元素将被自动赋值为 0.

示例代码: 一维数组的定义和引用

#include <stdio.h>
int main() {
// 定义并完全初始化
int nums1[] = {10, 20, 30, 40}; // 自动推断长度为4
// 定义固定长度数组(部分初始化)
int nums2[5] = {1, 2}; // [1,2,0,0,0]
// 访问元素
printf("第一个元素: %d\n", nums1[0]); // 输出: 10
// 修改元素
nums1[0] = 100;
printf("修改后: %d\n", nums1[0]); // 输出: 100
// 遍历数组(需获取长度)
int length = sizeof(nums1) / sizeof(nums1[0]);
printf("数组长度: %d\n", length); // 输出: 4
printf("遍历数组:");
for(int i = 0; i < length; i++) {
printf(" %d", nums1[i]); // 输出: 100 20 30 40
}
return 0;
}

6.2 二维数组的定义、初始化和数组元素的引用#

  • 定义: 二维数组声明格式为 类型标识符 变量名[m][n], 声明一个 mmnn 列的二维数组.
  • 引用: 通过 变量名[i][j] 引用元素, 其中 ii 为行下标 (0 到 m1m-1), jj 为列下标 (0 到 n1n-1).
  • 存储: 二维数组是按行顺序连续存储的. (一行一行)
  • 初始化: 可以分组初始化, 也可以省略第一维 (行) 的大小 (但不能省略其他维数, 如列数).

示例代码: 二维数组的定义和引用

#include <stdio.h>
int main() {
// 1. 定义并初始化二维数组(2行3列)
int matrix[2][3] = {
// 2. int matrix2[][3] 省略行数, 自动推断为2行
{1, 3, 5}, // 第一行
{2, 6, 10} // 第二行
};
// 3. 连续初始化方式
int matrix3[2][3] = {1, 2, 3, 4, 5, 6}; // 等价于{{1,2,3},{4,5,6}}
// 4. 访问元素:获取第二行第一列的元素(值为2)
printf("matrix[1][0] = %d\n", matrix[1][0]); // 输出: 2
// 5. 修改元素:将第一行第二列的元素改为100
matrix[0][1] = 100;
printf("修改后: matrix[0][1] = %d\n", matrix[0][1]); // 输出: 100
// 6. 遍历二维数组
int rows = sizeof(matrix) / sizeof(matrix[0]); // 计算行数
int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]); // 计算列数
printf("遍历matrix数组:");
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
printf("%d\t", matrix[i][j]); // 使用制表符对齐
}
printf(""); // 每行结束后换行
}
/* 输出:
1 100 5
2 6 10
*/
return 0;
}

6.3 字符串与字符数组#

  • 字符串本质: 在 C 语言中, 字符串是以 \0 结尾的字符数组, 而不是一种单独的数据类型. \0 是字符串结束标志符.
  • 定义: 可以通过字符数组来表示字符串.

示例代码: 字符串定义和引用

// 单引号定义并初始化字符
char c = 'a';
printf("%c\n", c); // 输出 'a'
// 双引号定义并初始化字符串 (会自动添加 \0)
char greetings[] = "Hello World!";
printf("%s\n", greetings);
// 字符数组初始化 (手动添加, 显式包含 \0)
char greetings2[] = {'H', 'e', 'l', 'l', '\0'};
printf("%s\n", greetings2); // 输出 "Hell"
// 访问/修改字符串中的字符
char greetings3[] = "Hello";
printf("%c\n", greetings3[0]); // 访问第一个字符 'H'
greetings3[0] = 'J'; // 修改第一个字符为 'J'
printf("%s\n", greetings3); // 输出 "Jello"

6.4 使用一维数组解决批量数据查找或排序等问题#

  • 一维数组常用于批量数据的查找和排序

  • 若数组无序, 采用顺序查找 ( 从头到尾依次比较 )

  • 若数组有序, 采用折半查找 ( 二分查找 ), 效率更高

    示例代码: 顺序查找

    // a 为数组, n 为长度, num 为待查找元素
    int found = 0; // 标志变量, 是否找到
    for (int i = 0; i < n; i++) { // 从头到尾遍历数组
    if (a[i] == num) { // 如果找到
    found = 1;
    break; // 跳出循环
    }
    }
    // found==1 表示找到, 否则未找到

    示例代码: 折半查找 ( 数组有序 )

    // a 为有序数组, n 为长度, num 为待查找元素
    int low = 0, high = n - 1, found = 0; // 初始化区间和标志
    while (low <= high) { // 只要区间不为空
    int mid = (low + high) / 2; // 取中间下标
    if (a[mid] == num) { // 找到
    found = 1;
    break;
    }
    else if (num > a[mid])
    low = mid + 1; // 在右半区间查找
    else
    high = mid - 1; // 在左半区间查找
    }
    // found==1 表示找到, 否则未找到
  • 排序常用选择排序、冒泡排序、插入排序, 都是基础算法, 适合小规模数据

  • 三者核心思想都是通过循环比较和交换, 逐步将数组变为有序

    示例代码: 选择排序:

    // a 为数组, n 为长度
    for (int i = 0; i < n - 1; i++) { // 外层循环, 控制趟数
    for (int j = i + 1; j < n; j++) { // 内层循环, 找最小值
    if (a[j] < a[i]) { // 如果有更小的值
    int t = a[j]; a[j] = a[i]; a[i] = t; // 交换元素
    }
    }
    }
    // 排序后数组 a 升序排列

    示例代码: 冒泡排序:

    // a 为数组, n 为长度
    for (int i = 0; i < n - 1; i++) { // 外层循环, 控制趟数
    for (int j = 0; j < n - 1 - i; j++) { // 内层循环, 相邻元素比较
    if (a[j] > a[j + 1]) { // 如果前面的比后面大
    int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; // 交换元素
    }
    }
    }
    // 排序后数组 a 升序排列

    示例代码: 插入排序:

    // a 为数组, n 为长度
    for (int i = 1; i < n; i++) { // 从第二个元素开始
    int k = a[i]; // 待插入元素
    int j = i - 1; // 比较的元素下标
    while (j >= 0 && k < a[j]) { // 向前查找插入位置
    a[j + 1] = a[j]; // 后移
    j--; // 继续向前比较
    }
    a[j + 1] = k; // 插入到合适位置
    }
    // 排序后数组 a 升序排列

7、函数定义与调用#

7.1 库函数的正确调用#

  • C 语言的系统库中提供了几百个函数可供程序员直接使用.
  • 使用库函数时, 要包含相应的头文件. 例如:
    • <stdio.h>: printf() (格式化输出), scanf() (格式化输入) .
    • <math.h>: sqrt() (平方根), pow() (幂运算), fabs() (绝对值) .
    • <stdlib.h>: rand() (伪随机整数), srand() (设置种子) .
    • <string.h>: strlen() (字符串长度), strcpy() (字符串复制) .
    • <time.h>: time() (获取当前时间), clock() (获取处理器时间) .

示例代码: 调用库函数

#include <stdio.h>
#include <math.h> // 需要包含 math.h 头文件
int main()
{
// 调用库函数 sqrt (平方根)
printf("%f", sqrt(16)); // 输出 4.000000
return 0;
}

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

  • 函数定义: 由函数头和函数体组成.
    • 函数头: 类型标识符 函数名(形式参数列表).
    • 函数体: 包含要执行的代码.
  • 函数类型与返回值:
    • 函数的类型 (即返回值的类型) 由函数头前的“类型标识符”指明.
    • 若没有返回值, 则使用 void.
    • 函数返回值通过 return 语句给出. 若函数无返回值, 可以不写 return.

示例代码: 自定义函数定义与返回值

// 函数定义: 返回 int 类型, 接受两个 int 参数
int myFunction(int x, int y)
{
return x + y; // 返回 x 和 y 的和
}
// 无返回值函数定义 (使用 void)
void greetUser(char name[])
{
printf("Hello %s\n", name);
}

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

  • 函数调用: 语法为 函数名(实际参数列表).
  • 值传递: 将实参的值传递给对应的形参.
    • 形参是局部变量, 在函数被调用时分配存储单元, 调用结束即被释放.
    • 对形参的任何改变都不会对实参产生任何影响 (单向传递).
  • 地址传递(数组): 将整个数组传递给被调函数时, 传递的是数组的首地址.
    • 在函数中对形参数组的任何修改都会影响到实参数组.

示例代码: 函数调用与值传递

// 假设 myFunction 已定义为 int myFunction(int x, int y) { return x + y; }
int main()
{
// 调用函数并将结果打印
printf("结果: %d", myFunction(5, 3)); // 传递 5 和 3 的值作为实参
int result = myFunction(5, 3); // 将结果存储在变量中
return 0;
}

7.4 函数的嵌套调用、递归调用#

  • 嵌套调用: 函数可以嵌套调用, 但不能嵌套定义.
  • 递归调用: 函数可以直接或间接调用自己.

示例代码: 嵌套调用(简单加法)

#include <stdio.h>
int add(int a, int b);
int main()
{
printf("结果: %d", add(add(1, 2), 3)); // 嵌套调用 add 函数
return 0;
}
int add(int a, int b)
{
return a + b;
}

示例代码: 递归调用(简单递归求和)

#include <stdio.h>
int sum(int n);
int main()
{
printf("结果: %d", sum(5)); // 计算 1+2+3+4+5
return 0;
}
int sum(int n)
{
if (n == 0) {
return 0; // 基础情况
} else {
return n + sum(n - 1); // 递归调用自身
}
}

7.5 局部变量与全局变量#

  • 局部变量: 在函数 (如形参和函数中定义的变量) 或语句块 (如循环体内定义的变量) 内有效 (可见).
  • 形式参数 (形参): 在函数定义时列出的参数, 它们本质上是局部变量, 仅在函数体内有效. 例如 void fun(int k) 中的 k.
  • 实际参数 (实参): 在函数调用时传入的值或表达式, 例如 fun(i) 中的 i, 实参可以是局部变量、全局变量、常量/表达式.
  • 全局变量: 在所有函数外定义, 其作用域为整个程序; 在它后面定义的函数中均可使用.
  • 同名变量的屏蔽: 若局部变量与全局变量同名, 则优先使用局部变量 (屏蔽全局变量) .
  • 外部变量声明: 若要在其他文件中使用未定义的全局变量, 则需声明其为外部变量, 使用 extern 数据类型名 变量名.

示例代码: 局部变量与全局变量

#include <stdio.h>
int k_global = 2; // 全局变量
int main()
{
int i = 5; // 局部变量
int x;
x = i + k_global;
printf("x=%d\n", x); // 使用全局变量 k_global, x = 7
{
int k_global = 16; // 语句块内的局部变量 (与全局变量同名)
x = i + k_global;
printf("x=%d\n", x); // 优先使用局部变量, x = 5 + 16 = 21
}
x = i + k_global;
printf("x=%d\n", x); // 语句块结束后, 恢复使用全局变量 k_global, x = 7
return 0;
}

示例代码: 形参 (局部) 与实参的来源

// fun 的 k 是形参(局部变量)
void fun(int k) {
printf("fun received %d\n", k);
}
int main() {
int i = 5; // main 内部的局部变量
fun(i); // i 作为实参传入
fun(10); // 常量 10 作为实参传入
return 0;
}

示例代码: 外部变量声明

// 示例:
// file1
int globalVar = 10; // 定义全局变量
// file2
#include <stdio.h>
extern int globalVar; // 声明外部变量
void printGlobalVar() {
printf("%d\n", globalVar);
}
C语言考查笔记
https://blog.chuwu.top/posts/2023-11-23/c-access/
作者
ChuwuYo
发布于
2023-11-23
许可协议
CC BY-NC-SA 4.0