代码之家  ›  专栏  ›  技术社区  ›  James Morris

确定C中的返回值的一般方法是什么?

  •  8
  • James Morris  · 技术社区  · 15 年前

    我的程序是用C for Linux编写的,并且有许多函数具有不同的返回值模式:

    1)一回或两回 n 论成功与否 -1 失败时。
    2)一些回报 0 论成功与否 - 1 失败时。
    3)有些在成功时返回1,在失败时返回0(我通常使用布尔类型拒绝)。
    4)指针返回 失败时(我通常不使用 NULL )

    前三个函数返回指针的函数总是返回 失败时,这很容易。

    第一个选项通常涉及返回长度为正的函数。

    第二个选项通常涉及命令行处理功能,但我不确定它是否正确,也许更好的值是exit-success和exit-failure?

    第三个选项用于在条件中方便、自然地调用的函数,我通常在这里使用 int 值1和0。

    尽管所有这些看起来都相当合理,但我仍然发现一些地方,这些地方不够清晰或明显,以至于在创建函数时使用哪种样式,或者在我希望使用函数时使用哪种样式。

    那么,在这里决定返回类型时,我如何为我的方法增加清晰度呢?

    8 回复  |  直到 14 年前
        1
  •  4
  •   Norman Ramsey    15 年前

    那么,在这里决定返回类型时,我如何为我的方法增加清晰度呢?

    拾取 每一个返回类型的模式和坚持它,否则你会让自己疯狂。根据长期为平台建立的约定来建模您的模式:

    • 如果要进行大量的系统调用,则任何整数返回函数都应返回 -1 失败论。

    • 如果您不进行系统调用,您可以自由地遵循C控制结构的约定,非零表示成功,零表示失败。(我不知道你为什么不喜欢 bool )

    • 如果函数返回指针,则应通过返回来指示失败 NULL .

    • 如果函数返回浮点数,则应返回NaN来指示失败。

    • 如果一个函数返回一个有符号和无符号整数的完整范围,那么您可能不应该在返回值中对成功或失败进行编码。

    测试返回值对C程序员来说是个祸害。如果失败很少,并且您可以编写一个中央处理程序,请考虑使用 exception macro package 可以指示故障,使用 longjmp .

        2
  •  4
  •   Tim Schaeffer    15 年前

    为什么不使用C标准库使用的方法?哦,等等…

        3
  •  3
  •   Christoph    15 年前

    不是你问题的真实答案,而是一些你可能会感兴趣的随机评论:

    • 在使用case(1)的时候通常是显而易见的,但是当涉及到无符号类型时会变得很难看。- return (size_t)-1 仍然有效,但不漂亮

    • 如果你用的是C99,那就没什么问题了 _Bool 在我看来,它比使用 int

    • 我使用 return NULL 而不是 return 0 在指针上下文中(Peronal首选项),但我很少检查它,因为我发现将指针作为布尔值处理更自然;常见情况如下:

      struct foo *foo = create_foo();
      if(!foo) /* handle error */;
      
    • 我尽量避免案例(2);使用 EXIT_SUCCESS EXIT_FAILURE 可能可行,但在我看来,这种方法只有在有两种以上的可能结果时才有意义,而且你必须使用 enum 无论如何

    • 对于更复杂的程序,实现自己的错误处理方案可能是有意义的;有一些相当高级的实现使用 setjmp() / longjmp() 大约,但我更喜欢吃点什么 errno -不同类型的错误有不同的变量

        4
  •  2
  •   sud03r    15 年前

    我能想到的一个条件是,上面的方法可能会失败,一个函数可以返回任何值,包括-1,比如一个函数加两个有符号的数字。

    在这种情况下,测试-1肯定是个坏主意。

    如果发生故障,我最好设置一个C标准提供的全局错误条件标志,格式为 errno 用它来处理错误。
    尽管C++标准库提供了异常,但它为错误处理付出了很多努力。

        5
  •  2
  •   Peter Mortensen icecrime    14 年前

    因为不能失败的决定论。使用更具体(bool)返回类型的是/否响应有助于保持一致性。对于更高级别的接口,您可能需要考虑返回或更新特定于系统的消息传递/结果详细结构。

    我对0始终成功的偏好基于以下观点:

    1. 零允许一些基本的分类,用负与正的值来组织失败,例如总失败与条件成功。我一般不建议这样做,因为它太浅,不太有用,可能导致危险的行为假设。

    2. 当success为零时,可以通过比较组的返回代码来进行一系列的正交调用,然后在单个条件下检查组是否成功。

      Rc=0; Rc++=函数(); Rc++=函数2(); Rc++=函数3-(); 如果(RC=0) 成功!

    3. 最重要的是,从我的经验来看,零似乎是在使用标准库和第三方系统时成功的一贯标志。

        6
  •  0
  •   Michael Burr    15 年前

    那么,在这里决定返回类型时,我如何为我的方法增加清晰度呢?

    你在想这件事,这件事有很长的路要走。如果你想出一个或两个规则——或者甚至更多,如果它们有意义(你可能需要不止一个规则——就像你提到的,你可能想处理返回的指针不同于其他东西),我认为你会比许多商店更好。

    我个人喜欢用0来表示失败,用非0来表示成功,但我没有足够的理由坚持这一点。我可以理解这种哲学,它可能想扭转这种感觉,这样你就可以返回失败的不同原因。

    最重要的是要遵循指导方针。更好的做法是制定有文件证明的指导方针(我相信,有了合理的指导方针,人们更容易遵守指导方针)。就像我说的,你在考虑这些事情,这一事实让你比其他许多人都强。

        7
  •  0
  •   t0mm13b    15 年前

    这是一个偏好问题,但我注意到的是不一致性。考虑使用pre-c99编译器

    #define SUCCESS  1
    #define ERROR    0
    

    然后任何返回int的函数,返回其中一个或另一个以最小化混淆并严格遵守它。同样,根据并考虑到开发团队,坚持他们的标准。

    在C99之前的编译器中,int为零是假的,任何大于零的都是真的。这取决于编译器的标准是什么,如果是c99,则使用stdbool的bool类型。

    C的最大优点是你可以使用你的个人风格,但是如果需要团队的努力,就要坚持团队制定的标准并认真遵循它,即使在你离开这个工作之后,另一个程序员也会感激你。

    保持一致。

    希望这有帮助, 最好的问候, 汤姆。

        8
  •  0
  •   Rasmus Kaj    15 年前

    许多C标准库使用该策略只在成功时返回true(或1),在失败时返回false(或0),并将结果存储在传入位置。比“it failed”更具体的错误代码存储在特殊变量errno中。

    像这样的东西 int add(int* result, int a, int b) 它将a+b存储在*result中并返回1(或者如果a+b恰好大于max,则返回0并将errno设置为适当的值)。