C 使用函数返回值进行错误检查和/或异常处理的技术是否正确?

C 使用函数返回值进行错误检查和/或异常处理的技术是否正确?,c,function,error-handling,exception-handling,return-value,C,Function,Error Handling,Exception Handling,Return Value,我继承了一个C系统,它使用函数返回值来检查错误和异常;大概是这样的: #define OK 1 int create_cheese(const char * myType, float myCost, char * myCheese) { // Do Stuff... if // everything looks good return 1; else return // error/exception code } int main() {

我继承了一个C系统,它使用函数返回值来检查错误和异常;大概是这样的:

#define OK 1

int create_cheese(const char * myType, float myCost, char * myCheese) {
   // Do Stuff...

   if // everything looks good
       return 1;
   else
       return // error/exception code
}

int main() {
    rc = create_cheese("cheddar", 12.99, &cheese);
    if (rc != OK) { exit(rc); }

    return 1;
}
这被认为是正确的C技术吗


这些功能不是很实用。换句话说,它们不使用函数返回值作为与程序执行相关的有意义的数据;它们用于错误和异常处理。谢谢,基思:^)

< p>是的,这是处理错误的完全有效的方法,特别是因为C没有异常,如C++或java。p> 检查返回值以查看函数是否成功,并使用参数从函数中获取信息。很多库函数都是以这种方式工作的,因此它是C中众所周知的idoim

您还可以混合返回有意义的值和错误代码。例如,
write
库函数返回读取的字节数,如果发生错误,则返回-1。在发生错误的情况下,它还会设置包含实际错误代码的全局
errno

这被认为是正确的C技术吗

我在C语言或标准库中没有找到匹配的并行成功返回1

C至少有6种不同的错误通信方式。下面列出了许多

OP发布的技术是返回错误/成功状态的变体

它有两个弱点

  • OK
    是一个太常见的标识符,可能会与其他代码冲突。太容易找到定义为0的
    OK

  • 相反的零度<代码>正常因为0更常见

OP的错误方法是不恰当的,因为它是现有技术的又一个不必要的变化


各种C错误/异常/不愉快的路径处理

  • 返回错误/成功(不是数据,但可能是错误数据)

    • Success为0,否则返回一个非零的
      errno\t
      :许多
      …\u s()
      函数。(类似于OP的——但非零成功)
    • 成功为0,否则为非零<代码>删除(),升高()
  • 返回数据-少数(可能只有一个)值表示错误/特殊

    • NULL
      不正确,否则为指针<代码>fgets()、setlocale()、bsearch()
    • NULL
      可能不正确,否则为指针<代码>malloc
    • 0不好,其他各种都好<代码>fread()
    • -1是坏的,其他各种都是好的<代码>时间(),fseek()
    • EOF
      -负数。0或更多是好的<代码>fgetc()
    • FP\u ILOGB0,FP\u ILOGBNAN
      其他一些
      int
      <代码>ilogb()
    • 任何负数都是不好的,否则值将提供信息<代码>printf()
    • 最大的几个值具有特殊含义,否则一些值不带符号<代码>mbrtoc16()
  • 通过状态/实例对象:许多I/O函数返回
    EOF
    ,以指示文件结束I/O错误。用于确定细节的其他函数
    feof()
    ferror()

  • 全球的

    • 错误代码
      errno
      strtol()
    • 浮点环境:
      fegetexceptflag()
  • 非数字:NaN在错误代码和值之间徘徊不定<代码>日志(负x),atanh(x大于1)

  • UB:不以指定方式处理错误:例如
    1/0



我在标准C库中没有看到的一种样式是其他库,它是
bool foo(…,int*error\u code)
-传递是存储/更新错误详细信息的地方。

这是正确的方法,但您可以遵循现有宏常量
EXIT\u SUCCESS
(=0)和
EXIT\u FAILURE
(=-1)的规则。所以我建议返回一个值
!=0出现错误时。

由于C不支持异常,在函数调用后测试错误的唯一方法是检查指定的错误保持变量。有几种方法可以做到这一点:

  • 从函数返回错误/成功指示(即
    errno\u t foo(int bar);

  • 将错误/成功指示作为输出指针参数(即
    void foo(int bar,errno\t*error\u code);

  • 使用操作系统错误指示器(即Windows上的
    SetLastError
    ,或
    errno

  • 我是方法#2的粉丝,因为很难忽略以下错误参数:

    errno_t err;
    myfunction(100, &err);
    
    而不是:

    errno_t err = myfunction(100); // You could just as easily not assign the return value
    
    C中的约定(在标准中几乎正式化)是返回0表示成功。所以你的返回1是特殊的,应该改变

    这可以扩展为故障时返回负值,接近故障时返回正值


    当从
    main
    返回时,您应该假设操作系统只处理返回值的8位,并且可能也不带符号,这与为失败返回负数是矛盾的!这就是标准的好处:有这么多可供选择。

    我给你一美元来列举这六种方法。说真的,我想知道。@kmiklas上周的最新帖子有一些-没有找到,我将列出一些..我知道你知道这一点,但从技术上讲,
    0.0/0.0
    是未定义的,尽管IEEE754定义了它。我会将所有返回错误状态(x是好的,y是坏的)聚集到一个类别中。这里的“几乎”是:Per:"... 如果status的值为零或
    EXIT\u SUCCESS
    。“我想找到一个不将
    EXIT\u SUCCESS
    定义为零的C实现。@AndrewHenle:是的,这真的很烦人。感谢你花时间在标准中找到这一点。我知道它是存在的