C:
处理错误
如何操作:
C 语言没有像其他一些语言那样内置对异常的支持。相反,它依赖于一些传统的错误处理策略,如从函数返回特殊值和设置全局变量如 errno
。
返回特殊值
函数可以通过返回一个不太可能是有效结果的特定值来指示错误。这里有一个关于整数的例子:
#include <stdio.h>
int inverse(int number, double *result) {
if (number == 0) {
return -1; // 错误情况
} else {
*result = 1.0 / number;
return 0; // 成功
}
}
int main() {
double result;
if (inverse(0, &result) < 0) {
printf("错误:除以零。\n");
} else {
printf("倒数是:%f\n", result);
}
return 0;
}
输出:
错误:除以零。
检查 errno
对于库函数,特别是那些与系统或操作系统(如文件 I/O)交互的函数,当发生错误时会设置 errno
。要使用它,需要引入 errno.h
并在怀疑失败后检查 errno
:
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("打开文件错误:%s\n", strerror(errno));
}
return 0;
}
输出:
打开文件错误:没有那个文件或目录
深入了解
历史上,C 编程语言的简约设计排除了内置的异常处理机制,反映了其底层系统编程的起源,其中最大的性能和接近金属层的控制至关重要。相反,C 采用了一种更手工的错误处理方法,符合其尽可能给程序员提供最大控制权的理念,即使这样做牺牲了便利性。
虽然这种方法与 C 的设计目标非常吻合,但它也可能导致冗长的错误检查代码和可能遗漏的错误检查,而现代语言则通过结构化异常处理机制解决了这个问题。例如,像 Java 或 C# 这样的语言中的异常允许进行集中错误处理,使代码更加清晰,错误管理也更加直接。然而,异常引入了它们的开销和复杂性,这可能不适合 C 所擅长的系统级编程。
尽管它的粗糙,C 中的手动错误处理已经影响了许多其他语言的错误管理设计,提供了一个模型,其中错误条件的明确性可以导致更可预测和可调试的代码。对于必须优雅管理失败的关键系统而言,C 的错误处理范式——结合现代最佳实践,如错误处理库和约定——确保了健壮性和可靠性。