C 语言 - 调试

调试

调试是查找并修复程序中错误的过程。

错误是使程序崩溃、行为异常或给出错误输出的错误。

在开始调试之前,请确保您的代码整洁有序:

  • 使用适当的缩进以保持结构清晰。
  • 为变量赋予清晰有意义的名称,描述它们存储的内容。

整洁的代码更易于阅读——也更易于调试!

在下面的章节中,我们将介绍几种常见的调试技巧。

1. 打印调试

在代码的不同位置使用 printf() 打印值,以查看哪里出了问题:

int x = 10;
int y = 0;
printf("Before division\n"); // 调试输出
int z = x / y; // 崩溃(除以零)
printf("After division\n"); // 永远不会执行

如果您没有看到 "After division",说明程序在 x / y 处崩溃了。

2. 检查变量值

打印变量以查看它们是否与预期相符:

int x = 10;
int y = 5;
int result = x - y;

printf("结果: %d\n", result); // 结果: 5

预期结果是 15?这意味着逻辑有误:尝试改用 x + y

3. 使用调试器工具

像 Visual Studio、Code::Blocks 和 VS Code 这样的 IDE 都内置了支持 C 语言的调试器。这些工具允许您:

  • 使用断点暂停程序
  • 逐行执行代码
  • 监视变量并查看它们变化时的意外值

提示:printf() 调试开始。一旦熟悉了,再探索您 IDE 的调试器,以获得对代码更深入的了解。

4. 从错误信息中学习

C 编译器和运行时错误通常会告诉您哪里出错了以及出错位置。例如:

error: expected ';' before 'printf'

简单的解决方案:修复缺少的分号!

使用安全检查进行调试

有些错误,例如除以零(在本页的第一个示例中使用过),已知会导致崩溃。

如果您知道某个操作可能失败,可以提前进行检查并避免崩溃:

实例

int main() {
  int x = 10;
  int y = 0;

  printf("Before division\n");

  if (y != 0) { // 在除法前检查 y 是否不为零
    int z = x / y;
    printf("结果: %d\n", z);
  } else {
    printf("Error: Division by zero!\n"); // 打印错误信息而不是崩溃
  }

  printf("After division\n");
  return 0;
}

亲自试一试

现在,程序不会崩溃,而是打印一条错误信息并继续运行。这是编写安全、可调试代码的重要组成部分。

另一个示例 - 数组越界访问

访问数组外部的元素是另一个常见错误。

在下面的示例中,我们使用 printf() 在使用索引值之前检查它:

实例

int main() {
  int numbers[3] = {10, 20, 30};
  int index = 5;

  printf("Index = %d\n", index);
  if (index >= 0 && index < 3) { // 确保索引在有效范围内(0 到 2)
    printf("Value = %d\n", numbers[index]);
  } else {
    printf("Error: Index out of bounds!\n");
  }

  return 0;
}

亲自试一试

总结

  • 使用 printf() 打印值并跟踪代码执行流程。
  • 仔细阅读错误信息——它们通常会告诉您哪里出错了以及出错位置。
  • 添加检查(如 if (y != 0))以避免崩溃发生。
  • 准备好进行更深入的调试时,使用 IDE 的调试器。
  • 调试有助于您更好地理解程序并更快地修复问题。

错误处理

调试是关于在开发过程中查找和修复代码中的错误,而错误处理则是在程序运行时处理问题的一种方式,当出现问题时执行特定的代码。

您将在接下来的章节中学习关于空指针错误处理的知识。