不可臆断返回值的意义
10.6.2 ID_wrongUseOfReturnValue
应遵循接口文档使用接口,不可臆断返回值的意义,否则造成逻辑错误。
示例:
void foo(const string& s) {
if (s.find("bar")) { // Non-compliant
....
}
}
例中 find 函数返回 "bar" 在 s 中的位置,当 s 中不存在 "bar" 时返回 string::npos,将 find 函数的返回值转为 bool 型是没有逻辑意义的。
应改为:
void foo(const string& s) {
if (s.find("bar") != string::npos) { // Compliant
....
}
}
想当然地认为返回 0 表示失败或不存在,非 0 表示成功或存在,是造成错误的常见原因。
又如:
bool gt(const char* a, const char* b) {
return strcmp(a, b) == 1; // Non-compliant
}
strcmp 函数的返回值可以是等于、大于或小于 0 的任意整数,分别对应字符串的等于、大于或小于关系,认为其只能返回 0、1 或 -1 是一种常见的误解。
应改为:
bool gt(const char* a, const char* b) {
return strcmp(a, b) > 0; // Compliant
}
strcmp、wcscmp 以及 memcmp 等函数不应与 0 之外的任何值比较。
下列函数的返回值不应与 0 比较,也不应转为 bool 型:
- open、create 等 Linux 系统调用,失败时返回负数,成功时返回非负数
- CreateFile、CreateNamedPipe 等 Windows API,失败时返回 INVALID_HANDLE_VALUE,而不是 0
- HRESULT 型 Windows API 返回值,负数表示失败、非负数表示成功
另外,有相当一部分函数成功时返回 0,失败时返回非 0,如 access、chmod、rename 等 Linux 系统调用,不可将其返回值当作 bool 型使用。
依据
ISO/IEC 9899:1999 7.21.4
ISO/IEC 9899:2011 7.24.4