应该没用的类型限定在返回时的类型被用,为清楚起见?
-
21-09-2019 - |
题
我们的静态分析工具抱怨的一个"无用的类型限定在返回时的类型"当我们有原型在头文件,例如:
const int foo();
我们将它定义这种方式,因为功能是返回的一个恒定的,将永远不会改变,认为API似乎清晰 const
在地方。
我觉得这是类似于明确的初始化的全球变量为零,为清楚起见,即使C的标准已经指出,所有globals将被初始化为零,如果不明确的初始化。在一天结束的时候,它确实并不重要。(但是静态的分析工具不会抱怨的。)
我的问题是,是没有任何理由,这可能引起一个问题吗?我们应该忽视的错误所产生的工具,或者我们应该安抚工具,在可能的成本的一个不太清楚和一致的API?(返回的其他 const char*
常量的工具没有问题。)
解决方案
它通常是更好地为你的代码,以尽可能准确地是怎么回事描述。你得到这个警告,因为在const
的const int foo();
基本上是没有意义的。该API只是看起来更清晰,如果你不知道什么const
关键字意味着做。不要超载意思那样; static
是够糟糕的,因为它是,而且也没有理由增加的潜力较为混乱。
const char *
指除const int
做,这就是为什么你的工具不会抱怨不同的东西。前者是一个指向字符串常量,这意味着任何代码调用该函数返回该类型不应该试图修改字符串的内容(这可能是在ROM为例)。在后一种情况下,系统没有办法强制执行,你不更改返回int
,所以预选赛是没有意义的。甲平行靠近返回类型将是:
const int foo();
char * const foo2();
这都将导致你的静态分析,给予警告 - 增加一个const限定一个返回值是一个毫无意义的操作。它才有意义当你有一个基准参数(或返回类型),例如您const char *
例子。
其实,我只是做了一个小测试程序,GCC甚至明确地警告说这个问题:
test.c:6: warning: type qualifiers ignored on function return type
所以,这不只是你的静态分析程序的抱怨。
其他提示
您可以使用不同的技术来阐明你的意图,而不会使工具不满。
#define CONST_RETURN
CONST_RETURN int foo();
您没有与const char *
一个问题,因为这是声明指针常量字符,而不是一个常量指针。
忽略const
现在,foo()
返回一个值。你可以做
int x = foo();
和分配由foo()
返回到可变x
的值,在大致相同的方式可以执行
int x = 42;
要分配值42
到变量x。结果
但你不能改变42
......或者foo()
返回的值。话说,从foo()
返回的值不能被施加const
关键字foo()
的类型而改变,无所作为。
<强>值强>不能const
(或restrict
,或volatile
)。只有对象有类型限定符。
对比度与
const char *foo();
在这种情况下,foo()
返回指向的对象。该目的通过返回可以是合格const
指向的值。
int是由返回的复制。这可能是一个const的副本,但是当它被分配到别的东西,某事凭借事实,这是分配的,不能被定义为一个常量。
在const关键字有语言中特定语义,而在这里你滥用它本质上是一个注释。而不是添加清楚起见,而暗示语言的语义的误解。
const int foo()
是从const char* foo()
很大的不同。 const char* foo()
返回一个数组(通常是一个字符串),其内容是不允许改变。想的区别是:
const char* a = "Hello World";
和
const int b = 1;
a
仍然是可变的,并且可以被分配到的是不能改变而b
其它串是不是一个变量。所以
const char* foo();
const char* a = "Hello World\n";
a = foo();
被允许但
const int bar();
const int b = 0;
b = bar();
是不允许的,甚至与const
的bar()
声明。
是的。我会建议编写代码"明确"的,因为它清楚地表明,任何人(包括自己在内)阅读时代码什么你的意思。你正在写的代码 其他程序员可读的, ,不要请随心所欲的编译器,静态分析工具!
(但是,你必须小心,任何这样的"不必要的代码"不会引起不同的代码生成的!)
一些例子明确的编码改善的可读性/可维护性:
我的地方括号部分的算术表达明确指定我想要什么发生。这清楚地表明,以任何读者什么我的意思是,保存我必担心(或使伊错误)优先顺序规则:
int a = b + c * d / e + f; // Hard to read- need to know precedence int a = b + ((c * d) / e) + f; // Easy to read- clear explicit calculations
在C++,如果复盖一个虚拟的功能,那么在得出类可以声明它没有提及"虚拟"。任何人阅读的代码不能告诉它是一个虚拟的功能,这可以是灾难性的误导!但是你可以安全地使用虚拟的关键词:
virtual int MyFunc()
这清楚地表明,任何人读你的类的头,这种方法是虚拟的。(这个"C++的语法错误"是固定在C#通过要求使用的"替代"关键词在这种情况下-更多证据,如果有人需要它,缺少出的"不必要的虚拟"是一个非常糟糕的主意)
这是两个明显的例子,其中添加"不必要的"代码会让的代码的更多的可读性和更不容易发生错误。