Error handling with return codes · 用返回码处理错误
C has no try/except
- Some languages throw exceptions when something goes wrong. C does not have exceptions.
- Instead, a C function reports trouble through its return value — a status code.
- The caller checks that code after every call and decides what to do.
C 没有 try/except
- 有些语言在出错时会抛出异常。C 没有异常。
- C 的函数通过它的返回值 —— 一个状态码 —— 来报告问题。
- 调用者在每次调用后检查这个状态码,再决定怎么做。
Return a status code
- A common rule: return
0for success and a negative number like-1for failure. - So
int do_thing(...)returns0when it worked,-1when it could not. - The real "answer" is then handed back a different way (see the next step).
返回状态码
- 一个常见的规则:成功返回
0,失败返回一个负数,比如-1。 - 所以
int do_thing(...)成功时返回0,做不到时返回-1。 - 真正的“答案”则用另一种方式交回(见下一步)。
Reporting the answer through an out-pointer
- If the return value is a status code, where does the real result go? Through an out-pointer.
- The caller passes the address of a variable; the function writes the answer with
*. - On failure, the function returns
-1and simply leaves that variable alone.
通过传出指针报告答案
- 如果返回值是状态码,那真正的结果放哪里?通过传出指针。
- 调用者传入一个变量的地址;函数用
*把答案写进去。 - 失败时,函数返回
-1,并且干脆不去碰那个变量。
Sentinels for "no value"
- A sentinel is a special value that means "nothing here":
-1for an index,NULLfor a pointer. - Functions use sentinels so the caller can tell success from failure with a simple check.
- Always check for the sentinel before you trust the result.
用哨兵值表示“没有值”
- 哨兵值是一个表示“这里什么都没有”的特殊值:下标用
-1,指针用NULL。 - 函数用哨兵值,好让调用者用一个简单的检查就能区分成功和失败。
- 在你信任结果之前,总是先检查哨兵值。
#include <stdio.h>
int safe_div(int a, int b, int *result) {
if (b == 0) return -1; // failure: cannot divide by zero
*result = a / b; // success: hand back the answer
return 0;
}
int main(void) {
int r;
if (safe_div(10, 2, &r) == 0) {
printf("%d\n", r); // 5
}
return 0;
}
Common mistakes
- Return a non-zero code from
mainto signal an error. - Check the return value of any function that can fail.
常见错误
- 从
main返回非零码表示出错。 - 检查任何可能失败的函数的返回值。
Now you try
- Return
0on success and-1on failure, and write the real answer through the out-pointer. - On failure, do not touch the out-pointer. Do not write a
main— the checker provides one.
现在轮到你了
- 成功返回
0,失败返回-1,把真正的答案通过传出指针写回去。 - 失败时不要碰传出指针。不要自己写
main—— 检查器会提供。
Complete int safe_div(int a, int b, int *result): if b is 0, return -1 and leave *result alone. Otherwise store a / b in · 入 *result and return 0. Do not · 不 write a main. · 完成 int safe_div(int a, int b, int *result):如果 b 是 0,返回 -1 且不碰 *result。否则把 a / b 存进 *result 并返回 0。不要写 main。
Click Run to see the output here. · 点击“运行”查看此处输出。
Complete int parse_int(const char *s, int *out): if s is a valid integer (digits, with an optional leading -), store its value in *out and return 0; otherwise return -1. Do not · 不 write a main. · 完成 int parse_int(const char *s, int *out):如果 s 是一个合法整数(数字,可带一个前导 -),把它的值存进 *out 并返回 0;否则返回 -1。不要写 main。
Click Run to see the output here. · 点击“运行”查看此处输出。
Complete int withdraw(int balance, int amount, int *new_balance): if amount is more than balance, return -1. Otherwise set *new_balance to · 到 balance - amount and return 0. Do not · 不 write a main. · 完成 int withdraw(int balance, int amount, int *new_balance):如果 amount 大于 balance,返回 -1。否则把 *new_balance 设为 balance - amount 并返回 0。不要写 main。
Click Run to see the output here. · 点击“运行”查看此处输出。