C 语言测验(实战指南)

C 语言测验:从基础到进阶的实战演练

你是否还在为 C 语言的指针、内存管理、函数调用感到头大?是否在写代码时总被“段错误”或“未定义行为”搞得焦头烂额?别担心,这正是大多数开发者成长路上的必经阶段。今天,我们不讲抽象的理论,而是通过一系列精心设计的 C 语言测验,带你一步步拆解核心概念,让每一个知识点都落地生根。

这些测验不是为了难倒你,而是为了帮你发现盲区、巩固基础。无论是刚入门的编程新手,还是想查漏补缺的中级开发者,都能从中收获实用技能。准备好了吗?让我们开始这场思维与代码的碰撞之旅。


基础语法与变量定义

C 语言是所有编程语言的“根”,它不提供自动内存回收,也不隐藏底层细节。这种“裸奔”式的语言特性,让你更接近计算机的本质,但也要求你对每一个变量、每一行代码都保持清醒。

在 C 语言中,变量的定义必须明确类型。比如:

int age = 25;
float height = 1.75;
char grade = 'A';

这里 int 表示整型,float 是单精度浮点数,char 存储单个字符。变量名可以是字母、数字、下划线的组合,但不能以数字开头。

💡 小贴士:想象变量就像一个带标签的抽屉,int age 就是给抽屉贴上“age”的标签,里面放的是整数。你不能往“age”抽屉里放小数,除非你换一个能放浮点数的抽屉。

下面这个测验题,检验你对变量作用域的理解:

#include <stdio.h>

int main() {
    int x = 10;
    
    if (x > 5) {
        int y = 20;
        printf("x = %d, y = %d\n", x, y);
    }
    
    // printf("y = %d\n", y);  // ❌ 编译错误!y 作用域仅限于 if 块内
    printf("x = %d\n", x);
    return 0;
}

注释说明:变量 y 是在 if 语句块内定义的,它的作用域仅限于该块。一旦跳出 ify 就不存在了。这是 C 语言的块级作用域机制,避免变量污染全局空间。


运算符与表达式解析

运算符是 C 语言的“算术工具箱”。常见的包括算术运算符(+、-、*、/、%)、关系运算符(>、<、==)、逻辑运算符(&&、||、!)等。

特别要注意的是,/% 的行为在整数和浮点数间有显著差异:

#include <stdio.h>

int main() {
    int a = 10, b = 3;
    float f_a = 10.0, f_b = 3.0;

    printf("整数除法: %d / %d = %d\n", a, b, a / b);       // 输出 3
    printf("浮点数除法: %.2f / %.2f = %.2f\n", f_a, f_b, f_a / f_b); // 输出 3.33

    printf("取模运算: %d %% %d = %d\n", a, b, a % b);      // 输出 1

    return 0;
}

注释说明a / b 是整数除法,结果自动向下取整。a % b 返回余数。而浮点数除法保留小数部分,更符合数学直觉。

⚠️ 常见陷阱:int x = 10 / 3; 结果是 3,不是 3.33。如果你想要精确结果,必须将变量声明为 floatdouble


控制结构:if、for、while 的实战应用

控制结构是程序的“大脑”,决定代码的执行路径。理解它们的运行逻辑,是写出正确程序的第一步。

if-else 的嵌套与优先级

#include <stdio.h>

int main() {
    int score = 85;

    if (score >= 90) {
        printf("优秀\n");
    } else if (score >= 80) {
        printf("良好\n");
    } else if (score >= 60) {
        printf("及格\n");
    } else {
        printf("不及格\n");
    }

    return 0;
}

注释说明else if 是链式判断,程序从上到下逐个检查条件。一旦某个条件为真,就执行对应代码块,并跳过后续所有分支。这就像“选择题”:选了 A,就不看 B 和 C。

for 循环的三要素

#include <stdio.h>

int main() {
    // 打印 1 到 10 的平方
    for (int i = 1; i <= 10; i++) {
        printf("%d 的平方是 %d\n", i, i * i);
    }

    return 0;
}

注释说明for 循环由三个部分组成:

  • 初始化:int i = 1,只在循环开始时执行一次
  • 条件判断:i <= 10,每次循环前检查
  • 更新:i++,每次循环结束后执行 三者缺一不可,顺序不可颠倒。

数组与字符串操作

数组是连续存储相同类型数据的容器。它像一排整齐的货架,每个货架编号(索引)对应一个商品。

创建数组与初始化

#include <stdio.h>

int main() {
    // 方法一:指定大小并初始化
    int numbers[5] = {1, 2, 3, 4, 5};

    // 方法二:自动推断大小
    int scores[] = {88, 92, 76, 95, 83};  // 大小为 5

    // 方法三:全部初始化为 0
    int zeros[10] = {0};  // 其余元素自动补 0

    // 遍历输出
    for (int i = 0; i < 5; i++) {
        printf("scores[%d] = %d\n", i, scores[i]);
    }

    return 0;
}

注释说明:数组索引从 0 开始。scores[0] 是第一个元素,scores[4] 是最后一个。访问越界(如 scores[5])会导致未定义行为,程序可能崩溃。

字符串的本质是字符数组

C 语言没有原生字符串类型,字符串用字符数组加 \0 结束符表示。

#include <stdio.h>

int main() {
    char name[] = "Alice";  // 自动添加 '\0'

    printf("名字是:%s\n", name);  // %s 用于输出字符串

    // 手动遍历字符串
    for (int i = 0; name[i] != '\0'; i++) {
        printf("字符 %d: %c\n", i, name[i]);
    }

    return 0;
}

注释说明\0 是字符串结束符,表示字符串的终点。printf 使用 %s 会从起始位置一直读取到 \0 为止。如果忘记加 \0,程序可能读取到内存垃圾数据。


函数设计与参数传递

函数是代码的“积木块”。合理封装功能,能让你的程序更清晰、可复用。

函数定义与调用

#include <stdio.h>

// 函数声明:告诉编译器这个函数存在
int add(int a, int b);

int main() {
    int result = add(5, 3);
    printf("5 + 3 = %d\n", result);
    return 0;
}

// 函数定义:实现具体逻辑
int add(int a, int b) {
    return a + b;
}

注释说明int add(int a, int b) 定义了一个接收两个整数参数、返回整数结果的函数。ab 是形参,在函数内部作为局部变量使用。

指针参数:传递地址

#include <stdio.h>

// 通过指针修改实参的值
void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main() {
    int a = 10, b = 20;
    printf("交换前:a = %d, b = %d\n", a, b);

    swap(&a, &b);  // 传递地址

    printf("交换后:a = %d, b = %d\n", a, b);
    return 0;
}

注释说明&a 取变量 a 的地址,int *x 表示 x 是一个指向整数的指针。*x 表示“指针指向的值”。通过指针,函数可以修改主函数中的变量,实现“传址调用”。


C 语言测验:综合实战

现在,来一场真正的 C 语言测验。请阅读以下代码,回答问题:

#include <stdio.h>

void modify(int *p, int n) {
    for (int i = 0; i < n; i++) {
        p[i] *= 2;
    }
}

int main() {
    int arr[4] = {1, 2, 3, 4};
    int size = 4;

    modify(arr, size);

    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

问题

  1. modify 函数的作用是什么?
  2. 为什么调用时传的是 arr 而不是 &arr
  3. 输出结果是什么?

答案提示

  1. 将数组每个元素乘以 2。
  2. 数组名 arr 本身就是一个指向首元素的指针,无需取地址。
  3. 输出:2 4 6 8

结语

C 语言测验不是终点,而是你深入理解底层逻辑的起点。从变量到函数,从数组到指针,每一个知识点都像一块积木,只有拼好才能搭建出稳固的程序大厦。

不要害怕犯错,错误是学习的阶梯。每一次编译失败、运行崩溃,都是在帮你建立“防御意识”——对内存、对指针、对边界。

当你能熟练写出一个完整的 C 程序,并能解释每行代码的含义时,你就真正掌握了这门语言。继续练习,继续思考,你离“高手”只差一个测验的距离。