std*_*all 41 c coding-style lint return-value
最近,我开始使用lint进行静态代码分析.我有时得到的一个警告就是这个问题.比方说,我有以下功能:
uint32_t foo( void );
Run Code Online (Sandbox Code Playgroud)
让我们说我故意忽略函数的返回值.为了使警告消失,人们可以写
(void) foo();
Run Code Online (Sandbox Code Playgroud)
我的问题是,编写这样的代码的"正确"方法是什么,我应该像往常一样继续,因为编译器不会抱怨它,或者我应该使用void来清楚,所以其他代码维护者会知道我刻意忽略了返回值.
当我看到这样的代码(带有空白)时,我觉得很奇怪......
mou*_*iel 56
常见的方法是在foo();
不投入的情况下打电话(void)
.
从来没有忽视过printf()
回报价值的人,铸就了第一块石头.
小智 30
我个人比较喜欢的"未使用"的警告,但有时也有,我都不理他们(实例例如,write()
用户,或fscanf(...,"%*s\n")
或strtol()
在返回值是不重要的,我只是想的副作用[也许]移动文件指针.)
使用gcc 4.6,它变得非常棘手.
(void)
不再有效.{ssize_t ignore; ignore=write(...);}
抛出另一个警告(已分配 - 未使用).write(...)+1
抛出另一个警告(计算值 - 未使用).抑制这些的唯一好处(如果丑陋)是将返回值转换为编译器同意您可以忽略的内容.
例如,(void)(write(...)+1)
.
这显然是进步.(并且+0
不起作用,BTW.)
Ale*_*lds 17
使用Clang和GCC编译器执行此操作的一种方法是pragma
:
/* ... */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
foo(); /* this specific unused-result warning gets ignored during compilation */
#pragma GCC diagnostic pop
/* ... */
Run Code Online (Sandbox Code Playgroud)
本push
- pop
组合包装的ignored
指令,这样的警告可以在其他地方在你的代码被触发.对于那些阅读源代码的人来说,看看这个代码块的功能应该会更容易.
要使静态代码检查器有用,它还应报告忽略的返回值,这可能导致很难跟踪错误 - 或者错过错误处理.
所以你应该保持(void)
或停用支票printf
.现在,您可以通过多种方式以可读的方式执行此操作.我用来将函数包装在一个新函数中,例如
void printf_unchecked(const char* format, ...)
Run Code Online (Sandbox Code Playgroud)
不太好的演员阵容发生的地方.也许在这种情况下使用预处理器宏来实现它更实际,因为varargs ...
指示未使用结果的一种稍微"漂亮"的方式是:
/**
* Wrapping your function call with ignore_result makes it more clear to
* readers, compilers and linters that you are, in fact, ignoring the
* function's return value on purpose.
*/
static inline void ignore_result(long long int unused_result) {
(void) unused_result;
}
...
ignore_result(foo());
Run Code Online (Sandbox Code Playgroud)
有了C++
,这可以扩展到:
template<typename T>
inline void ignore_result(T /* unused result */) {}
Run Code Online (Sandbox Code Playgroud)
我喜欢用标志来编译代码:
$gcc prog1.c -o prog1.x -Wall -Wextra -ansi -pedantic-errors -g -O0 -DDEBUG=1
Run Code Online (Sandbox Code Playgroud)
为了避免这种情况,-Wunused-result
我不喜欢添加另一个标志的想法:(-Wno-unused-result
如果这样做,那就是一个解决方案)。
我曾经强制转换(void)
为某些函数(不printf
编译或不使用其他著名函数,因为编译器不会警告它们,只是奇怪的函数)。现在强制转换为(void)
不再起作用(GCC 4.7.2)
有趣的夹板建议:
Result returned by function call is not used. If this is intended,
can cast result to (void) to eliminate message. (Use -retvalother to
inhibit warning)
Run Code Online (Sandbox Code Playgroud)
但这不再是解决方案。夹板需要有关此问题的更新。
因此,以一种非常兼容的方式摆脱警告,这是一个好习惯MACRO
:
/** Turn off -Wunused-result for a specific function call */
#define igr(M) if(1==((int)M)){;}
Run Code Online (Sandbox Code Playgroud)
并这样称呼它:
igr(PL_get_chars(t, &s, CVT_VARIABLE));
Run Code Online (Sandbox Code Playgroud)
它的外观整洁,任何编译器都将省去代码。下面是我最喜欢的编辑的照片vi
:左窗,否igr()
;中间窗口,使用igr()
; 右窗口,来源。
您可以看到,完全相同的完全无害的代码让C做gcc不会做的事情:忽略返回代码。
1==...
仅为了避免夹板警告此条件为否,才需要进行比较BOOL
。海湾合作委员会一点也不在乎。根据功能,您可能会收到cast
警告。我进行了一个测试,忽略了double
这个MACRO,这很好,但是我不完全相信。特别是如果函数返回指针或更复杂的东西。
在这种情况下,您还需要:
#define pigr(M) if(NULL==((void *)M)){;}
Run Code Online (Sandbox Code Playgroud)
最后一件事:{;}
由于出现-Wempty-body
警告,所以这是必需的(在“ if”语句中,建议将大括号括在空主体周围)。
并且(现在是最后一件事);
函数调用之后(严格地)不是必需的,而是良好的实践。使您的代码行更加同质,所有代码行均以结尾;
。(它被翻译为NOP
助记符,经过优化后消失了)。
运行编译器不会发出警告或错误。运行splint
给出:
$ splint ./teste.c -I/usr/lib/swi-prolog/include/ -strict-lib
Splint 3.1.2 --- 20 Feb 2009
Finished checking --- no warnings
Run Code Online (Sandbox Code Playgroud)
另请参阅此答案