我最近想出了一种我认为是在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文件)中声明不同的返回状态不会生成警告或错误。
答案 0 :(得分:6)
一个主要问题是,您不能使用编译器对标头和实现进行交叉检查,因为实现TU(翻译单元)(即问题中的implementation.c
)不能包含标头( implementation.h
),因为枚举常量将被双重定义,这是不允许的。这意味着编译器无法发现服务的提供者和使用者之间的不一致之处。使用者可以使用标头,但提供者(implementation.c
)不能。
此外,只有一个功能可以使用OK
(或INTERNAL_ERROR
或NO_PARAMETERS
)-其他功能的“无错误”状态需要使用不同的名称,而每个功能都需要使用不同的名称错误状态。因此,即使它可以用于单个功能,但即使是小型软件也不是一个实用的解决方案(但这不是一个好主意)。
顺便说一下,请注意,尽管do_that()
有声明,但标头或实现文件中都没有原型。该函数声明为带有不确定的参数列表-众所周知,它不是形式变量函数(没有省略号...
),并且其所有参数均受default argument promotion规则约束(大致而言:char
和short
被提升为int
; float
被提升为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?