why a variable declared but not used may cause a error? - c++

If i declare a variable but not use it later in the program, the complier will give me a warning, and since "every warning should not be ignored", why the warning is there? and how can it cause a error? thanks!

First, a minor point: declaring a variable that's never used is a waste of memory, and thus is itself a bug.
Second, and more importantly: you took the trouble of writing out a declaration for a variable you then never used. Since you would not have bothered to declare a variable if you had no plan to use it, this suggests you've forgotten to use it! Is it possible you typed the wrong variable name in its place? Is it possible you forgot to perform a critical calculation whose result you'd store in that variable?
Of course, you might just have declared something you ended up not needing, which is why it's a warning and not an error, but it's easy to see situations where that warning can point you to an important piece of missing code, which would indeed be a bug.

It's there because maybe you meant to use the variable. You generally don't declare a variable and then use not it :)
It's a helpful warning, and it exists in most languages.
It may assist in detecting typos, where you accidentally used another variable instead of the one you meant to, this warning will remind you of the one that you haven't used :)

It doesn't cause an error. It causes a warning (normally only at higher levels on most compilers) because the variable isn't doing anything, which might indicate that you intended to use it but didn't. Sometimes that might indicate that your code is behaving incorrectly.
It's not that the code could fail as it is, just that the compiler's trying to warn you that you've done something a little odd.

It may indicate the presence of a bug, a variable that is declared but unused is obviously a programming error, since why else would it be there at all?

Are you asking about something like this?
int function() {
double x;
return 42;
}
There's a warning saying the variable x is unused because, well, it's unused. It is a warning because if a variable is unused, it does nothing*.
You may fall into this warning if you mistype or accidentally shadow a variable. For instance:
void printArgument10Times(int i) {
for(int i = 0; i < 10; ++i) {
std::cout << i << std::endl;
}
}
// ...
printArgument10Times(42);
Instead of printing 42 ten times, it prints 0 through 9. i was shadowed and was also unused. The compiler will hopefully tell you both these things.
*In C++ constructors and deconstructors are called, of course.

Related

What will a "single variable as a statement" do?

Below is the C++ function in a project I took over lately. Each of the last two statements is just a variable, containing no assignment. What will such kind of statement do? Lately, I saw such kinds of statements usually.
__fastcall TCardActionArea::TCardActionArea(TComponent* Owner)
:TArea(Owner,"CardActionArea")
{
// Get the thread id
ThreadId = std::__threadid();
this->Visible= false;
m_pBackGroundPicture = NULL;
m_pActionButtonMap.clear();
m_ActionsButtonDisplayed.clear();
m_changecnt = 0;
m_isNextbtn = true;
m_PictureParamPath1;
m_PictureParamPath2;
}
Normally, these statements do not do anything, and it is definitely not a common practice to write them.
Maybe the author just wanted to explicitly note that they do not need to assign any values to these members (although a comment would do better).
Maybe this is some hack for a particular compiler to prevent some optimization (e.g. to prevent the member from being optimized away), but it would be a very slippery hack that may not work on a next compiler version.
Maybe the author intended to assign something to these variables and just forgot to do this, so this may be a bug.
Or maybe the author just had some kind of template, e.g. listing all the members to make sure they did not forgot anything, and just kept the parts of template they did not need to change.
The only time I've seen statements like this used was to silence compiler warnings about unreferenced variables (usually function arguments). I haven't checked whether MSVC (which features of this code lead me to believe was used, at least originally) issues such warnings about unused members, although that does seem a stretch as it would only work in some whole-code analysis mode.

Why gcc and clang both don't emit any warning?

Suppose we have code like this:
int check(){
int x = 5;
++x; /* line 1.*/
return 0;
}
int main(){
return check();
}
If line 1 is commented out and the compiler is started with all warnings enabled, it emits:
warning: unused variable ‘x’ [-Wunused-variable]
However if we un-comment line 1, i.e. increase x, then no warning is emitted.
Why is that? Increasing the variable is not really using it.
This happen in both GCC and Clang for both c and c++.
Yes.
x++ is the same as x = x+1;, the assignment. When you are assigning to something, you possibly can not skip using it. The result is not discarded.
Also, from the online gcc manual, regarding -Wunused-variable option
Warn whenever a local or static variable is unused aside from its declaration.
So, when you comment the x++;, it satisfies the condition to generate and emit the warning message. When you uncomment, the usage is visible to the compiler (the "usefulness" of this particular "usage" is questionable, but, it's an usage, nonetheless) and no warning.
With the preincrement you are incrementing and assigning the value to the variable again. It is like:
x=x+1
As the gcc documentation says:
-Wunused-variable:
Warn whenever a local or static variable is unused aside from its declaration.
If you comment that line you are not using the variable aside of the line in which you declare it
increasing variable not really using it.
Sure this is using it. It's doing a read and a write access on the stored object. This operation doesn't have any effect in your simple toy code, and the optimizer might notice that and remove the variable altogether. But the logic behind the warning is much simpler: warn iff the variable is never used.
This has actually the benefit that you can silence that warning in cases where it makes sense:
void someCallback(void *data)
{
(void)data; // <- this "uses" data
// [...] handler code that doesn't need data
}
Why is that? increasing variable not really using it.
Yes, it is really using it. At least from the language point of view. I would hope that an optimizer removes all trace of the variable.
Sure, that particular use has no effect on the rest of the program, so the variable is indeed redundant. I would agree that warning in this case would be helpful. But that is not the purpose of the warning about being unused, that you mention.
However, consider that analyzing whether a particular variable has any effect on the execution of the program in general is quite difficult. There has to be a point where the compiler stops checking whether a variable is actually useful. It appears that the stages that generate warnings of the compilers that you tested only check whether the variable is used at least once. That once was the increment operation.
I think there is a misconception about the word 'using' and what the compiler means with that. When you have a ++i you are not only accessing the variable, you are even modifying it, and AFAIK this counts as 'use'.
There are limitations to what the compiler can identify as 'how' variables are being used, and if the statements make any sense. In fact both clang and gcc will try to remove unnecessary statements, depending on the -O-flag (sometimes too aggressively). But these optimizations happen without warnings.
Detecting a variable that is never ever accessed or used though (there is no further statement mentioning that variable) is rather easy.
I agree with you, it could generate a warning about this. I think it doesn't generate a warning, because developers of the compilers just didn't bothered handling this case (yet). Maybe it is because it is too complicated to do. But maybe they will do this in the future (hint: you can suggest them this warning).
Compilers getting more and more warnings. For example, there is -Wunused-but-set-variable in GCC (which is a "new" warning, introduced in GCC 4.6 in 2011), which warns about this:
void fn() {
int a;
a = 2;
}
So it is completely fine to expect that this emits a warning too (there is nothing different here, neither codes do anything useful):
void fn() {
int a = 1;
a++;
}
Maybe they could add a new warning, like -Wmeaningless-variable
As per C standard ISO/IEC 9899:201x, expressions evaluation are always executed to allow for expression's side effects to be produced unless the compiler can't be sufficiently sure that removing it the program execution is not altered.
5.1.2.3 Program execution
In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).
When removing the line
++x;
The compiler can deduce that the local variable x is defined and initialized, but not used.
When you add it, the expression itself can be considered a void expression, that must be evaluated for side effects, as stated in:
6.8.3 Expression and null statements
The expression in an expression statement is evaluated as a void expression for its side effects.
On the other hand to remove compiler warnings relative to unused variable is very common to cast the expression to void. I.e. for an unused parameter in a function you can write:
int MyFunc(int unused)
{
(void)unused;
...
return a;
}
In this case we have a void expression that reference the symbol unused.

Getting warning for non-const variables which are not modified

When declaring a variable as a const and trying to modfiy its value later, you will get a compiler error. For example this code:
void func(){
const int a = 5;
a = 4;
}
will generate error C3892 on MSVS. However, if the opposite case happened, no error nor warning will be thrown. For example, this code:
void func(){
int a = 5;
std::cout << a;
}
won't produce any warning even with /wall configuration. I know that this code is not buggy. It is just does not follow the best practice.
Why there is no warning for such thing? is it only on MSVS? Does the standard have anything to say about that? Are there another compilers that produce a warning for this?
When declaring a variable as a const and trying to modifiy its value later, you will get a compiler error.
That's right, that's because you try misleading your compiler by telling it that you are not going to modify something, and then modifying it later.
Why there is no warning for such thing?
Because there is nothing misleading about that. Declaring a variable non-const does not tell the compiler that you are going to modify it, only that you want to have an option to modify it later.
Does the standard have anything to say about that?
No. Although the standard talks about the other case (modifying a const), it does not say anything about not modifying a non-const.
One reason for this is that finding a modification of a const is a trivial task, because it happens in one place. However, finding that there are no modifications of a non-const requires the compiler to look through the entire scope of the variable from the point of its declaration on. That is why finding potential const applications is left for program verification and refactoring tools.

Need help regarding macro definition

Im reading c++ code, i have found such definition
#define USE_VAL(X) if (&X-1) {}
has anybody idea, what does it mean?
Based on the name, it looks like a way of getting rid of an "unused variable" warning. The intended use is probably something like this:
int function(int i)
{
USE_VAL(i)
return 42;
}
Without this, you could get a compiler warning that the parameter i is unused inside the function.
However, it's a rather dangerous way of going about this, because it introduces Undefined Behaviour into the code (pointer arithmetic beyond bounds of an actual array is Undefined by the standard). It is possible to add 1 to an address of an object, but not subtract 1. Of course, with + 1 instead of - 1, the compiler could then warn about "condition always true." It's possible that the optimiser will remove the entire if and the code will remain valid, but optimisers are getting better at exploiting "undefined behaviour cannot happen," which could actually mess up the code quite unexpectedly.
Not to mention that fact that operator& could be overloaded for the type involved, potentially leading to undesired side effects.
There are better ways of implementing such functionality, such as casting to void:
#define USE_VAL(X) static_cast<void>(X)
However, my personal preference is to comment out the name of the parameter in the function definition, like this:
int function(int /*i*/)
{
return 42;
}
The advantage of this is that it actually prevents you from accidentally using the parameter after passing it to the macro.
Typically it's to avoid an "unused return value" warning. Even if the usual "cast to void" idiom normally works for unused function parameters, gcc with -pedantic is particularly strict when ignoring the return values of functions such as fread (in general, functions marked with __attribute__((warn_unused_result))), so a "fake if" is often used to trick the compiler in thinking you are doing something with the return value.
A macro is a pre-processor directive, meaning that wherever it's used, it will be replaced by the relevant piece of code.
and here after USE_VAL(X) the space it is explain what will USE_VAL(X) do.
first it take the address of x and then subtract 1 from it. if it is 0 then do nothing.
where USE_VAL(X) will used it will replaced by the if (&X-1) {}

Why is there no warning when I write an empty main?

If I write a program like the following one, g++ and visual studio have the courtesy of warning me that the local variable a is never used :
int main()
{
int a; // An unused variable? Warning! Warning!
}
If I remove the unused variable (to make the compiler happy), it leaves me with the following program :
int main()
{
// An empty main? That's fine.
}
Now, I am left with a useless program.
Maybe I am missing something, but, if an unused variable is bad enough to raise a warning, why would an empty program be ok?
The example above is pretty simple. But in real life, if I have a big program with an empty main (because I forgot to put anything in it). Then having a warning should be a good thing, isn't it.
Maybe I am missing an option in g++ or visual studio that can raise a warning/error when the main is empty?
The reason for this is simple, if there is no return statement in main it implicitly returns EXIT_SUCCESS, as defined by the standard.
So an empty main is fine, no return needed, no function calls needed, nothing.
To answer the question why GCC doesn't warn you is because warnings are there to help you with common mistakes. Leaving a variable unused can lead to confusing errors, and code bloat.
However forgetting entirely to write a main function isn't a common mistake by anything but a beginner and isn't worth warning about (because it's entirely legal as well).
I suspect a lot of it is that compilers generally try to warn about things that are potential problems, but aren't necessarily apparent.
Now it's certainly true that if all your main contains a definition of a variable that's never used, that's fairly apparent -- but if you've defined 16 variables (or whatever) and one of them is no longer used, that may not be so obvious.
In the case of main containing nothing, I suppose the same could happen with an empty main -- for example, you could have a whole web of #ifdef/#elif/etc., that led to main being entirely empty for some particular platform. I'm pretty sure I've never run across this though, and I'm pretty sure I've never heard of anybody else seeing it either. At least to me, that suggests that it probably doesn't arise often enough in practice for most people to care much about the possibility.
if an unused variable is bad enough to raise a warning, why would an empty program be ok?
First of all, an empty main does not equal an empty program. There could be static objects with non-trivial constructors/destructors. These would get invoked irrespective of whether main is empty.
Secondly, one could think of lots and lots of potential errors that a compiler could warn about, but most compilers don't. I think this particular one doesn't come up very often (and takes seconds to figure out). I therefore don't see a compelling case for specifically diagnosing it.
When I was cleaning up inherited C code that comprised the customized runner for Informix 4GL, I fixed every warning having set the warning flag to catch everything, and there were lots of warnings.
I haven't used Visual C++ in a long time. Can't VC++ be configured to flag the most severe warnings? It is probably not the default setting, but one you have to change.
It is possible then that at least the unused variable would be flagged.
In a global sense int main() is just a definition of the main function of the program which returns SUCCESS when finishes.
The main function is the point by where all C++ programs start their execution, independently of its location within the source code.
So this:
int main()
{
// An empty main? That's fine.
// notice that the "return 0;" part is here by default, whether you wrote it or not
}
is just a definition of a function which returns admissible value.
So everything is ok, that's why the compiler is silent.