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) {}
Related
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.
Browsing among some legacy code I've found such function:
static inline bool EmptyFunc()
{
return (void*) EmptyFunc == NULL;
}
What are the differences from this one:
static inline bool EmptyFunc()
{
return false;
}
This code was created to compile under several different platforms, like PS2, Wii, PC... Are there any reason to use the first function? Like better optimization or avoiding some strange compiler misbehavior?
Semantically both functions are the same: they always return false*. Folding the first expression to a constant value "false" is completely allowed by the standard since it would not change any observable side-effects (of which there are none). Since the compiler sees the entire function it also free to optimize away any calls to it and replace it with a constant "false" value.
That is, there is no "general" value in the first form and is likely a mistake on the part of the programmer. The only possibility is that it exploits some special behaviour (or defect) in a specific compiler/version. To what end I don't know however. If you wish to prevent inlining using a compiler-specific attribute would be the correct approach -- anything else is prone to breaking should the compiler change.
(*This assumes that NULL is never defined to be EmptyFunc, which would result in true being returned.).
Strictly speaking, a function pointer may not be cast to a void pointer, what happens then is outside the scope of the standard. The C11 standard lists it as a "common extension" in J.5.7 (I suspect that the same applies in C++). So the only difference between the two cases in that the former is non-portable.
It would seem that the most likely cause of the former version is either a confused programmer or a confused compiler. We can tell for certain that the programmer was confused/sloppy by the lack of an explaining comment.
It doesn't really make much sense to declare a function as inline and then try to trick the compiler into not inlining the code by including the function address in the code. So I think we can rule out that theory, unless of course the programmer was confused and thought it made sense.
Sorry for the vague title, but not really sure how to phrase it. So I was looking through the innards of boost::asio (trying to track down some ridiculous delays), and I notice code like this dotted about:
op_queue<operation> completed_ops;
task_cleanup c = { this, &lock, &completed_ops };
(void)c; // EH?
Now from the name of the struct that is being initialized, I'm guessing it's using RAII to do some steps on destruction - fine, but what is the purpose of the last line? Have I just missed something completely funky?
Maybe to avoid a compilation warning because c isn't used?
It's probably there because it's a cross-platform method of getting the compiler not to complain about an unused variable.
The question was probably meant to be about why it's used, and that's already been answered. I'm going to talk about what it means (which the OP probably already knows, but others may not). At least one other question has been closed as a duplicate of this one.
In general, casting an expression to void evaluates the expression and discards the result, if any. In this case, the expression is c, the name of a variable of type task_cleanup (whatever that is).
An expression followed by a semicolon is an expression statement. When the statement is executed, the expression is evaluated and its result is discarded.
So this:
(void)c;
evaluates c (which, since c is just a non-volatile declared object, just fetches the value of the object), then discards the result, then discards the result again.
Semantically, this doesn't make much sense. You might as well just write:
c;
or even omit it entirely with exactly the same effect.
The purpose, as the other answers have already said, is to suppress a warning that the variable's value is not used. Without the cast, many compilers will warn that the result is discarded. With the cast, most compilers will assume that you're deliberately discarding the value, and will not warn about it.
This is no guarantee; compilers can warn about anything they like. But casting to void is a sufficiently widespread convention that most compilers will not issue a warning.
It probably would have been worthwhile to call the variable ignored rather than c, and a comment would definitely be helpful.
In C++ one can write any of the following statements:
10;
true;
someConstant; //if this is really an integer constant
or something like
int result = obtainResult();
result; // looks totally useless
The latter can be used to suppress a compiler warning "A variable is initialized but not referenced" (C4189 in VC++) if a macro that is expanded into an empty string in some configuration is later used with the result variable. Like this:
int result = obtainResult();
result;
assert( result > 0 ); // assert is often expanded into an empty string in Release versions of code
What's the meaning of such statements? How can they be used except for compiler warning suppression?
This kind of statements is a logical expansion of how other pieces of the language works. Consider having a function that returns a value, for example int foo(), that also has some side effects. Sometimes you only want those side effects to happen, so you write foo(); as a statement.
Now, while this does not look exactly like 10;, the function call will evaluate to an int sooner or later, and nothing happens to that int, just like with 10;.
Another example of the same issue is that since you can do a = b = 10;, that means b = 10 has to evaluate to 10, hence you can not do assignment without generating a value that has to be suppressed.
Being able to write such values as statements is just a logical way of building the language, but for the cases you present it might even be a good idea to give a compiler warning for it.
Unless you use it to suppress compiler warnings ;)
These statements (called expression-statements in the C++ grammar) are valid because they are expressions.
Expressions are all constructs that calculate some kind of value, such as
3 + 5
someVariable
someFunctionCall( 2 )
someVar += 62
val > 53
I think, to keep the grammar simple, they decided to not differentiate between those expressions that actually have a side effect (such as the function call or the assignment) and those that don't.
Such a statement does nothing, and will most likely be optimized away by any decent compiler.
It may be useful for getting rid of the unused variable warning, but with some compilers you may get a statement has no effect warning instead.
They have no practical use beyond compiler warning suppression, and in general the compiler will elide any such constant-value statement that has no side effect.
They are expressions that will be evaluated, assuming the compiler doesn't optimise them away. As for "meaning", I'm not sure what you "mean" by that!
In C and C++, a statement that is just an expression is evaluated.
The fact that the expression might be useless is harmless, and with the optimizer turned on can result in no code generated at all. However, as you've observed, it usually does count as use of a variable.
Note that statements containing only an expression are quite common. A simple function call is one, for example. In printf("hello, world.\n");, the return value of printf() is ignored but the function is still called and its intended effect (text output) happens.
Also, a variable assignment x = 3; is also a statement made up of a simple expression, since assignment is an operator and returns a value in addition to its side effect of modifying the lvalue.
Although legal I think these statements are confusing and should be avoided, even for suppressing warnings. For me it is more reasonable to suppress the warning using something like this:
int result = 0;
result = obtainResult();
assert (result > 0);
In some embedded enviroments accessing a read only register will have side effects, e.g. clearing it.
Writing int temp = IV; to clear it causes a warning because temp isn't used, in which case I write IV;
I agree with Magnus' answer. There is one thing that puzzles me though: why do you use this nonsense
int result = obtainResult();
result; // looks totally useless
to get rid of compiler warnings? In my humble opinion it is much worse NOT to have a warning in such situation. The result variable is still not used - you have just "swept the dirt under the carpet". This "lone variable" approach looks as if there was something missing (Have I accidently deleted something?). Why don't you use
(void)obtainResult();
in the first place? It assures anyone who would be reading your code that you do not care about the return result. It is very difficult to put this "accidently". Obviously this does not generate any compiler warnings.
I am working on a C++ project and I noticed that we have a number of warnings about unused parameters.
What effect could it have if these warnings are ignored?
The function with an unused parameter may have a real bug in the following cases:
There is an output parameter, which is not being assigned or written into, resulting in undefined value for the caller.
One of parameters is a callback function pointer, which you must invoke and forget to do so. May happen if there is a lot of #ifdefs in the function.
You declare a local variable with the same name that shadows a parameter and subsequently use the wrong value down in the function.
Not using an input parameters may be harmless, but you can reduce the noise to see useful warnings by marking unused input parameters explicitly in the beginning of the function by casting it to void (works for both C and C++):
(void)param1;
Or,
#define UNUSED(expr) do { (void)(expr); } while (0)
...
void foo(int param1, int param2)
{
UNUSED(param2);
bar(param1);
}
Or omit parameter name (C++ only):
void foo(int param1, int /*param2*/)
{
bar(param1);
}
If you have a whole lot of unimportant warnings that are not important to you, you may overlook the important warning about the line of code that you just wrote that is hiding in the middle of them.
For a gcc specific way to disable the warning, you can use __attribute__((unused)) like
void foo(int a, int b __attribute__((unused))) {
}
To ignore the second parameter. If your program relies on GCC technologies already, you can use that attribute to be 100% safe from that kind of warning.
It means you wrote a function that takes a parameter but doesn't use the parameter. It's harmless but it might indicate bugs in some cases.
Generally you can silence this warning by removing the parameter name, leaving it anonymous, but that may not be desirable depending on why the parameter is not being used.
I'd suggest you turn off the warning if it is making it harder to find the real problems.
In C++ you can have default arguments:
int sum(int first, int second=0){ // should not give warning
return first+first;
}
You can also have extra argument:
int sum(int first, int second){ // should give warning
first *= 2;
return first;
}
If you have a parameter you're not using and it's not defaulted, you should get a warning because you're asking the program to pass extra values to the stack that are never referenced, and therefore is doing more work than it should.
Maybe it means you forgot part of the function logic, too.
None. except [EDIT]: as others have pointed out, You could have an unassigned output parameter.
You should clean them up, because on many occasions I have seen developers ignore important warnings that were 'hidden' in amongst a large number of warnings, and they were so used to seeing warnings they never paid any attention to them. I try to have zero warnings at all times, and set compiler warnings to the maximum level.
That depends of if you intended to use the paramater. E.g.
const int Size = 12; // intended for use in some other function
char* MakeBuffer(int size)
{
return new char[Size];
}
In this code 'size' is unused, and instead the constant 'Size' is being used. So the warning will highlight problems of this type for you.
However, if you never indented to use the parameter then it should just be removed from the method signature. Unless you need to match a signature for a virtual method, or function pointer, if that's the case then you don't have the option to remove it.
If a method doesn't use a parameter then the first question that arises is that why is that parameter a part of the method's signature in the first place. These warnings do make sense since it is bad design that these are referring to and further, there is a little overhead as well that whenever this method is called, this parameter is pushed on the stack so, the best is to refactor the method and remove such parameters which do not have any use.
Having said that, leaving these parameters doesnt harm a lot except for a little overhead that I mentioned.