是否可以在C中返回不同的“ false”?

时间:2019-01-26 20:49:08

标签: c return return-value

我正在为realloc写一个包装器。对于返回值,我使用以下代码:

typedef enum { SALLOC_OK, SALLOC_OVERFLOW, SALLOC_ALLOCFAIL, ... } salloc_rc;

这在这样的函数中使用:

salloc_rc salloc(<args>) {
    if(blabla) return SALLOC_OVERFLOW;
    if(blabla) return SALLOC_ALLOCFAIL;
    /* More error codes */
    return SALLOC_OK;
}

这当然不是完整的代码,但是足以演示我想要的内容。到目前为止,一切都很好。我可以这样检查返回值:

if(salloc(a,b) != SALLOC_OK) // Handle error

或者,如果我想更精确一点:

if(salloc(a,b) == SALLOC_OVERFLOW) // Handle overflow

但是,我希望它与检查错误的常规方法兼容。我希望能够使用:

if(!salloc(a,b)) // Handle error

if(salloc(a,b) { /* Do stuff */ }
else { /* Handle error */ }

这里的问题是0为假,其他所有为真。我想做的事情似乎是不可能的,但是围绕它可能有一些我错过的方法。到目前为止,我发现的唯一解决方案是为该函数提供一个额外的参数,并带有一个指向可以存储错误代码的位置的指针,但是我想尽可能避免这种情况。

TL; DR

如何使函数<type> foo()能够根据出了什么问题返回不同的错误消息,同时仍保持以“传统”方式检查错误的可能性,例如

if (!foo()) exit(EXIT_FAILURE);

3 个答案:

答案 0 :(得分:3)

如果您写

if (! salloc(a,b)) handleError();

那是完全错误的。严重的错误。但是如果你写

if (salloc(a, b)) handleError();

然后,作为您的代码阅读者,我不知道该声明是否正确,这迫使我阅读文档。因此,正确的方法是:

salloc_rc returnCode = salloc(a, b);
if (returnCode != SALLOC_OK) handleError();

这很干净,它可以告诉读者确切的情况,它使您有机会在您检查返回代码的地方设置一个断点。赢了。不要担心一些额外的击键。使您的代码可读。而且,如果您被告知使“代码检查错误的常用方法”难以阅读,那么请不要使用“代码检查错误的常用方法”。

请注意,在许多其他现代语言(Java,Swift)中,不能将枚举用作if语句中的条件或用作!的参数。 (不)。该死,我只是将Java称为“更现代的语言”:-(

答案 1 :(得分:3)

如果只需要一个成功代码和多个错误代码,则有多种选择。
没有一个是自然的/惯用的,因此就好像事情正好相反:

  1. 使用一些辅助空间来获取其他信息:

    1. 使用errno为有兴趣的人运送补充信息。
      标准库可以做到这一点。

    2. 将特定错误存储在使用的对象中。 fgetc()使用feof()ferror()

    3. 为补充的错误信息定义自己的(线程本地)存储。

    4. 使用回调或其他输出指针。

    5. 返回一个struct,其中包含您需要的所有成员。

  2. 使用反向逻辑,这意味着只有false才是成功。
    这提醒我们使用诸如strcmp()之类的常规比较功能来检查相等性。

  3. 将某些返回值范围专用于错误:

    1. 使用负数表示错误。令人高兴的是,您拥有成功的所有非负面因素。
      COM does that extensivelytheir HRESULT。与许多Linux系统调用一样。

    2. 浮点数通常具有许多NaN值。可以在其中放置细节,有些架构甚至可以保证以最小的代码传播。不幸的是,这种方法很少使用,花费很少,因此没有遵循新的说明。

    还有一些不太方便的示例。

我的建议是,如果可以的话,将其存储在被操纵的对象中,然后存储errno,然后是取反的逻辑,最后是COM约定。

答案 2 :(得分:1)

通常情况恰好相反。

 if(salloc(a,b)) // Handle error

 if(USB_Transmit(a,b)) // Handle error

这是一个非常简单的逻辑-如果函数返回的非零值-则表示存在错误。

现实生活中的例子: STM库: / *遵循USB设备状态* /

typedef enum {
  USBD_OK   = 0,
  USBD_BUSY,
  USBD_FAIL,
}USBD_StatusTypeDef;

#define NRF_SUCCESS                           (NRF_ERROR_BASE_NUM + 0)  ///< Successful command
#define NRF_ERROR_SVC_HANDLER_MISSING         (NRF_ERROR_BASE_NUM + 1)  ///< SVC handler is missing
#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED      (NRF_ERROR_BASE_NUM + 2)  ///< SoftDevice has not been enabled
#define NRF_ERROR_INTERNAL                    (NRF_ERROR_BASE_NUM + 3)  ///< Internal Error
#define NRF_ERROR_NO_MEM                      (NRF_ERROR_BASE_NUM + 4)  ///< No Memory for operation
#define NRF_ERROR_NOT_FOUND                   (NRF_ERROR_BASE_NUM + 5)  ///< Not found
#define NRF_ERROR_NOT_SUPPORTED               (NRF_ERROR_BASE_NUM + 6)  ///< Not supported
#define NRF_ERROR_INVALID_PARAM               (NRF_ERROR_BASE_NUM + 7)  ///< Invalid Parameter
#define NRF_ERROR_INVALID_STATE               (NRF_ERROR_BASE_NUM + 8)  ///< Invalid state, operation disallowed in this state
#define NRF_ERROR_INVALID_LENGTH              (NRF_ERROR_BASE_NUM + 9)  ///< Invalid Length
#define NRF_ERROR_INVALID_FLAGS               (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
#define NRF_ERROR_INVALID_DATA                (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
#define NRF_ERROR_DATA_SIZE                   (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size
#define NRF_ERROR_TIMEOUT                     (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
#define NRF_ERROR_NULL                        (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
#define NRF_ERROR_FORBIDDEN                   (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
#define NRF_ERROR_INVALID_ADDR                (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
#define NRF_ERROR_BUSY                        (NRF_ERROR_BASE_NUM + 17) ///< Busy
#define NRF_ERROR_CONN_COUNT                  (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded.
#define NRF_ERROR_RESOURCES                   (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation

其中NRF_ERROR_BASE_NUM通常为0