Our static analysis tool complains about a \"useless type qualifier on return type\" when we have prototypes in header files such as:
const int foo();
It's usually better for your code to describe as accurately as possible what's going on. You're getting this warning because the const
in const int foo();
is basically meaningless. The API only seems clearer if you don't know what the const
keyword means. Don't overload meaning like that; static
is bad enough as it is, and there's no reason to add the potential for more confusion.
const char *
means something different than const int
does, which is why your tool doesn't complain about it. The former is a pointer to a constant string, meaning any code calling the function returning that type shouldn't try to modify the contents of the string (it might be in ROM for example). In the latter case, the system has no way to enforce that you not make changes to the returned int
, so the qualifier is meaningless. A closer parallel to the return types would be:
const int foo();
char * const foo2();
which will both cause your static analysis to give the warning - adding a const qualifier to a return value is a meaningless operation. It only makes sense when you have a a reference parameter (or return type), like your const char *
example.
In fact, I just made a little test program, and GCC even explicitly warns about this problem:
test.c:6: warning: type qualifiers ignored on function return type
So it's not just your static analysis program that's complaining.
The int is returned by copy. It may be a copy of a const, but when it is assigned to something else, that something by virtue of the fact that it was assignable, cannot by definition be a const.
The keyword const has specific semantics within the language, whereas here you are misusing it as essentially a comment. Rather than adding clarity, it rather suggests a misunderstanding of the language semantics.
Yes. I would advise writing code "explicitly", because it makes it clear to anyone (including yourself) when reading the code what you meant. You are writing code for other programmers to read, not to please the whims of the compiler and static analysis tools!
(However, you do have to be careful that any such "unnecessary code" does not cause different code to be generated!)
Some examples of explicit coding improving readability/maintainability:
I place brackets around portions of arithmetic expressions to explicitly specify what I want to happen. This makes it clear to any reader what I meant, and saves me having to worry about (or make ay mistakes with) precedence rules:
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
In C++, if you override a virtual function, then in the derived class you can declare it without mentioning "virtual" at all. Anyone reading the code can't tell that it's a virtual function, which can be disastrously misleading! However you can safely use the virtual keyword:
virtual int MyFunc()and this makes it clear to anyone reading your class header that this method is virtual. (This "C++ syntax bug" is fixed in C# by requiring the use of the "override" keyword in this case - more proof if anyone needed it that missing out the "unnecessary virtual" is a really bad idea)
These are both clear examples where adding "unnecessary" code will make the code more readable and less prone to bugs.
Ignoring the const
for now, foo()
returns a value. You can do
int x = foo();
and assign the value returned by foo()
to the variable x
, in much the same way you can do
int x = 42;
to assign the value 42
to variable x.
But you cannot change the 42
... or the value returned by foo()
. Saying that the value returned from foo()
cannot be changed, by applying the const
keyword to the type of foo()
accomplishes nothing.
Values cannot be const
(or restrict
, or volatile
). Only objects can have type qualifiers.
Contrast with
const char *foo();
In this case, foo()
returns a pointer to an object. The object pointed to by the value returned can be qualified const
.
You can use a different technique to illustrate your intent without making the tools unhappy.
#define CONST_RETURN
CONST_RETURN int foo();
You don't have a problem with const char *
because that's declaring a pointer to constant chars, not a constant pointer.
const int foo()
is very different from const char* foo()
. const char* foo()
returns an array (usually a string) whose content is not allowed to change. Think about the difference between:
const char* a = "Hello World";
and
const int b = 1;
a
is still a variable and can be assigned to other strings that can't change whereas b
is not a variable. So
const char* foo();
const char* a = "Hello World\n";
a = foo();
is allowed but
const int bar();
const int b = 0;
b = bar();
is not allowed, even with the const
declaration of bar()
.