问题描述
如果我使用特定功能而不检查其返回值,我希望编译器发出错误。
I want the compiler to emit an error if I'm using a specific function without checking its return value.
我在eclipse中使用GCC。
I'm using GCC in eclipse.
例如:
int fun (){ return 3;}
void main ()
{
printf("%d",fun ());
}
我将函数称为 fun
并打印返回值,但我不检查返回值。相反,我想强制执行以下操作:
I call the function fun
and print the return value but I do not check the return value. Instead, I would like to enforce something like this:
int ret=fun();
if(ret != some_value) { /* Do something */ }
printf("%d",fun ());
这可能吗?
推荐答案
您不能强制进行适当的支票
我认为没有任何方法可以按照您想要的方式进行。毕竟,在语句 printf(%d,fun())
中,实际上是在检查 fun()$的返回值。 c $ c>发送到另一个函数。当然,
printf
并没有真正检查返回值,但是您可以这样使用它:
You cannot force a proper check
I don't think there is any way to do that in the way you want it. After all, in the statement printf("%d",fun ())
you are actually checking the return value from fun()
by sending it to another function. Of course, printf
doesn't really "check" the return value, but you could have used it this way:
void exit_if_fun_returns_negative_value(int val) { if(val<0) exit(EXIT_FAILURE); }
int main(void)
{
exit_if_fun_returns_negative_value(fun());
}
但是没有办法让编译器理解它与您的代码之间的区别 printf
语句。我假设您想强迫程序员将返回值保存在变量中,但是我不知道该怎么做,即使您可以这样做,也不能确保正确的检查。只是看这个例子:
But there is no way to make the compiler understand the difference between this and your printf
statement. I assume you want to force the programmer to save the return value in a variable, but I don't know how that should be done, and even if you could do that, it does not ensure a proper check. Just look at this example:
char *array;
void *ptr;
ptr = realloc(array, 20);
strcpy(array, "Hello, World!");
请注意我们如何将返回值保存在 ptr $ c $中c>,但是由于我们没有执行
if(ptr == NULL)exit(EXIT_FAILURE);
这样的事情,所以毫无意义。
Note how we are saving the return value in ptr
but since we're not doing something like if(ptr == NULL) exit(EXIT_FAILURE);
it's pretty pointless.
但是,有一种方法可以防止不使用的语句(当然与实际检查不同)返回值。
However, there is a way to prevent statements where you're not using (which of course is not the same thing as actually checking) the return value at all.
据我所知,没有便携式的方法可以做到这一点。您将不得不依赖编译器扩展。 Gcc具有这样的扩展名。
As far as I know, there is no portable way to do this. You will have to rely on compiler extensions. Gcc has such an extension.
__attribute__ ((warn_unused_result)) int foo (void)
{
return 5;
}
int main(void)
{
foo();
}
编译此命令将产生以下警告:
Compiling this will generate this warning:
$ gcc main.c
main.c: In function ‘main’:
main.c:9:5: warning: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Wunused-result]
9 | foo();
| ^~~~~
为了将其视为错误,请使用 -Werror
In order to treat it as an error, compile with -Werror
$ gcc main.c -Werror
main.c: In function ‘main’:
main.c:9:5: error: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Werror=unused-result]
9 | foo();
| ^~~~~
cc1: all warnings being treated as errors
如果要全部其他警告只是警告,请使用 -Werror = unused-result
进行编译。例如:
If you want all other warnings to be just warnings, compile with -Werror=unused-result
. Example:
$ cat main.c
__attribute__ ((warn_unused_result))
int foo (void)
{
return 5;
}
int main(void)
{
int *x = 5;
foo();
}
$ gcc main.c -Werror=unused-result
main.c: In function ‘main’:
main.c:9:14: warning: initialization of ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
9 | int *x = 5;
| ^
main.c:10:5: error: ignoring return value of ‘foo’, declared with attribute warn_unused_result [-Werror=unused-result]
10 | foo();
| ^~~~~
cc1: some warnings being treated as errors
将签名更改为包括输出参数
要完成类似操作的一个方法是将返回值移至参数。这将强制将返回值保存到参数,并且您必须在不向其发送输出变量的情况下调用该函数。更改
Change the signature to include an output parameter
One option to accomplish something similar is to move the return value to a parameter. That will force saving the "return value" to the parameter, and you cannot call the function without sending an output variable to it. Change
int fun (){ return 3;}
至
void fun(int *ret) { *ret=3; }
但是如上所述,我看不到如何强制正确检查变量。
But as I mentioned above, I cannot see how you can force a proper check of the variable. This only forces an assignment.
另一种选择是使用包装函数。这通常会大大降低灵活性,因此在使用它之前请三思而后行,但这是一个在某些情况下可能有用的选项。假设您有一个标头/源对。将包装器的原型放在头文件中,并将包装器和函数的实现放入源文件中。这将对程序员隐藏原始功能。看起来可能像这样:
Another option is to use wrapper functions. This will often greatly reduce the flexibility so think twice before using it, but it is an option that could be useful in some cases. Let's say that you have a header/source pair. Put the prototype of the wrapper in the header file and the implementation of both the wrapper and the function in the source file. That will hide the original function from the programmer. It can look like this:
.h
int fun_wrapper();
.c
int fun() { return 3; }
int fun_wrapper()
{
int ret = fun();
if(ret<0) exit(EXIT_FAILURE);
return ret;
}
如何将此技术用于库函数
我创建了一个具有答案的相关问题。它是关于如何将此功能用于库中的 fgets
和其他功能的:
这篇关于如果未检查函数返回值,如何强制编译错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!