将函数签名中的枚举声明为返回状态

时间:2019-04-09 06:43:46

标签: c enums language-lawyer return-value

我最近想出了一种我认为是在C代码中声明函数返回状态的奇怪方法。执行任务的功能通常会根据成功或错误返回状态代码。这通常以整数或枚举的形式发送,该声明在文件(或另一个文件)中的其他位置声明。我发现通过在函数签名中声明枚举,我们可以:

  • 使可能的返回值接近函数签名
  • 每个函数都有一组唯一的返回值,避免使用未使用的值

例如像这样:

// implementation.h
enum {
    OK,
    INTERNAL_ERROR,
    NO_PARAMETERS
} do_that();

// implementation.c
enum {
    OK,
    INTERNAL_ERROR,
    NO_PARAMETERS
} do_that() {
    if (this())
        return OK;
    else if (that())
        return NO_PARAMETERS;
    return INTERNAL_ERROR;
}

我从未见过有人使用这种风格;有效吗如果没有,为什么不呢?

我看到的一个缺点是,您必须在c文件和头文件中都声明可能的返回值,但这也使它更可用,并且在查看签名时可以直接清除。

另一个问题是,据我了解,即使在学究的c语言中,枚举类型之间也可以进行隐式转换,这意味着在函数声明和实现(c和h文件)中声明不同的返回状态不会生成警告或错误。

3 个答案:

答案 0 :(得分:6)

一个主要问题是,您不能使用编译器对标头和实现进行交叉检查,因为实现TU(翻译单元)(即问题中的implementation.c)不能包含标头( implementation.h),因为枚举常量将被双重定义,这是不允许的。这意味着编译器无法发现服务的提供者和使用者之间的不一致之处。使用者可以使用标头,但提供者(implementation.c)不能。

此外,只有一个功能可以使用OK(或INTERNAL_ERRORNO_PARAMETERS)-其他功能的“无错误”状态需要使用不同的名称,而每个功能都需要使用不同的名称错误状态。因此,即使它可以用于单个功能,但即使是小型软件也不是一个实用的解决方案(但这不是一个好主意)。

顺便说一下,请注意,尽管do_that()有声明,但标头或实现文件中都没有原型。该函数声明为带有不确定的参数列表-众所周知,它不是形式变量函数(没有省略号...),并且其所有参数均受default argument promotion规则约束(大致而言:charshort被提升为intfloat被提升为double)。如果该函数不带参数,则应将其写为do_that(void),以便在声明完成后有可用的原型。

答案 1 :(得分:1)

这是不合法的,因为第一个枚举与第二个枚举不同,因此声明和定义具有不兼容的签名,即使它们的常量成员相同。

引用6.2.5类型p。 16

  

每个不同的枚举构成一个不同的枚举类型

答案 2 :(得分:0)

尝试:

#include <stdio.h> 
// implementation.h
enum {
    OK,
    INTERNAL_ERROR,
    NO_PARAMETERS
} do_that();

// implementation.c
enum {
    OK,
    INTERNAL_ERROR,
    NO_PARAMETERS
} do_that() {
    if (mytest == 0)
        return OK;
    else if (mytest == 1)
        return NO_PARAMETERS;
    return INTERNAL_ERROR;
}

int main() 
{ 
    printf("do_that(%d) = %d\n",0,do_that(0));
    printf("do_that(%d) = %d\n",1,do_that(1));
    printf("do_that(%d) = %d\n",2,do_that(2));
    return 0; 
} 

礼物:

Main.c:11:5: error: redefinition of enumerator 'OK'
    OK,
    ^
Main.c:4:5: note: previous definition is here
    OK,

所以你不能:

  • 在.c中包含您的.h。

  • 声明函数原型

为什么不只使用typedef?