接手一个C模块,接口注释只写了一句失败返回-1。调用方把返回值直接赋给size_t,然后memcpy了4GB,进程当场挂掉。return -1这个约定到处都在用,含义却要看上下文。
作为错误码:配合errno
POSIX里大量函数失败返回-1,具体原因放在errno。open返回-1可能是ENOENT也可能是EACCES,必须立刻读errno,因为下一个库函数调用可能把它覆盖。写法是先保存int e = errno,再用strerror(e)打印。Windows的API不一样,失败返回0或INVALID_HANDLE_VALUE,错误码用GetLastError取。
作为查找失败:indexOf的惯例
Java的String.indexOf、JavaScript的Array.indexOf、C的strchr找不到时都返回-1,因为0是合法下标。判断时要写idx不等于-1,而不是直接if(idx),后者在找到第0个元素时会误判。
无符号类型下的灾难
size_t n = read(fd, buf, len); if (n == -1) { /* 永远不成立 */ }-1赋给无符号数会变成最大值,比较时-1被转换成SIZE_MAX,条件恒假。正确做法是把返回值存进ssize_t或有符号int,判完再转。
main返回-1会变成255
进程退出码只取低8位,return -1到shell里echo $?显示255。脚本里判断退出码等于255才准。想表达失败,规范写法是return 1或EXIT_FAILURE。
所以看到-1,先确认三件事:是有符号还是无符号、-1表示错误还是没找到、错误细节从哪取。接口文档里把这三点写清楚,比事后加日志省事得多。