转换为void不会删除warn_unused_result错误

Mic*_*ior 12 c gcc gcc-warning

在测试中,我丢弃了任何东西,stderr因为它使测试用例的输出变得混乱.我正在使用以下代码:

freopen("/dev/null", "w", stderr);
Run Code Online (Sandbox Code Playgroud)

编译时-Wall -Werror,我得到错误

error: ignoring return value of ‘freopen’, declared with attribute warn_unused_result
Run Code Online (Sandbox Code Playgroud)

这是预料之中的.但是,通常的铸造解决方案void似乎不起作用.也就是说,将代码更改为

(void) freopen("/dev/null", "w", stderr);
Run Code Online (Sandbox Code Playgroud)

仍然会产生相同的警告.我不在乎这个函数是否失败,因为最坏的情况是一些额外的输出.我可以解决这个问题吗?

编辑:我知道我可以引入一个额外的不必要的变量.我真的很想知道为什么无法转换为无效.

更新: 我决定采用这个:

FILE *null = fopen("/dev/null", "w");
if (null) { fclose(stderr); stderr = null; }
Run Code Online (Sandbox Code Playgroud)

freopen仔细阅读文档之后,我看到如果打开/dev/null失败,stderr仍然会被销毁.这解决了这个问题.

Hug*_*ugh 12

对GCC扩展有点重,但没有外部可见的变量:

#define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; })
ignore_result(freopen("/dev/null", "w", stderr));
Run Code Online (Sandbox Code Playgroud)


Jon*_*ler 5

为什么不简单地使用结果,因为警告建议你应该.

if (freopen("/dev/null", "w", stderr) == 0)
    ...oops...lost stderr...hard to report errors...
Run Code Online (Sandbox Code Playgroud)

由于函数是使用'warn_unused_result'属性声明的,因此除非使用返回值,否则将收到警告.由于函数在失败时返回null或在成功时返回文件流参数,因此您可能会考虑分配结果.但是,你不应该像这样分配给stderr(见下文),所以这是一个坏主意:

stderr = freopen("/dev/null", "w", stderr);
Run Code Online (Sandbox Code Playgroud)

从理论上讲,你应该进行检查; 存在可能无法打开"/ dev/null"的可怕(并且难以置信)的情况.


C99标准中的脚注229注释:

229)的主要用途的的freopen功能是改变(与标准文本流相关联的文件stderr,stdinstdout),如那些标识符不必是可修改的左值,其通过所述返回的值fopen函数可以被分配.

因此,任务是不明智的.但是测试返回值会处理编译器警告,也可能有助于防止核心转储.但是,它不太可能改善您的代码覆盖率数据(错误路径不会经常采用;很难强制覆盖错误处理).

请注意,POSIX描述freopen()有一些关于设计的适度刻薄的评论freopen(),这是由C标准委员会(1989版)发明的,可能没有来自POSIX的输入.