What is the purpose of the statement "(void)c;"? - c++

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.

Related

Why can I pass a reference to an uninitialized element in c++?

Why does the following code compile?
class Demo
{
public:
Demo() : a(this->a){}
int& a;
};
int main()
{
Demo d;
}
In this case, a is a reference to an integer. However, when I initialize Demo, I pass a reference to a reference of an integer which has not yet been initialized. Why does this compile?
This still compiles even if instead of int, I use a reference to a class which has a private default constructor. Why is this allowed?
Why does this compile?
Because it is syntactically valid.
C++ is not a safe programming language. There are several features that make it easy to do the right thing, but preventing someone from doing the wrong thing is not a priority. If you are determined to do something foolish, nothing will stop you. As long as you follow the syntax, you can try to do whatever you want, no matter how ludicrous the semantics. Keep that in mind: compiling is about syntax, not semantics.*
That being said, the people who write compilers are not without pity. They know the common mistakes (probably from personal experience), and they recognize that your compiler is in a good position to spot certain kinds of semantic mistakes. Hence, most compilers will emit warnings when you do certain things (not all things) that do not make sense. That is why you should always enable compiler warnings.
Warnings do not catch all logical errors, but for the ones they do catch (such as warning: 'Demo::a' is initialized with itself and warning: '*this.Demo::a' is used uninitialized), you've saved yourself a ton of debugging time.
* OK, there are some semantics involved in compiling, such as giving a meaning to identifiers. When I say compiling is not about semantics, I am referring to a higher level of semantics, such as the intended behavior.
Why does this compile?
Because there is no rule that would make the program ill-formed.
Why is this allowed?
To be clear, the program is well-formed, so it compiles. But the behaviour of the program is undefined, so from that perspective, the premise of your question is flawed. This isn't allowed.
It isn't possible to prove all cases where an indeterminate value is used, and it isn't easy to specify which of the easy cases should be detected by the compiler, and which would be considered to be too difficult. As such, the standard doesn't attempt to specify it, and leaves it up to the compiler to warn when it is able to detect it. For what it's worth, GCC is able to detect it in this case for example.
C++ allows you to pass a reference to a reference to uninitialized data because you might want to use the called function as the initializer.

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) {}

What is the use of a statement with no effect in C++? [duplicate]

This question already has answers here:
What is the purpose of the statement "(void)c;"?
(3 answers)
Closed 8 years ago.
In one library that I am using I saw this code:
template<typename T>
void f(SomeTemplatedClass<T> input)
{
(void)input;
...
use(input); // code that uses input
}
I have no idea what is the meaning of this code. If I remove the cast to void, I get a
statement has no effect
warning in gcc. So I suppose someone did it purposefully and purposefully added the cast to get a rid of the warning.
Do you have any experience with a statement that has no effect, yet it is needed for some reason?
EDIT:
Is it safe to assume that this has nothing to do with templates? For example circumventing an old compiler bug or the like?
This construct is a common way of tricking the compiler into not emitting a warning for unused parameters. I have not seen it used for any other purpose.
(void)input;
While it is common, it is also a really bad idea.
it is highly platform dependent -- it may work on one compiler and not another.
it is unnecessary. There is always a better way to deal with unused parameters. The modern way is to simply omit the parameter name.
it can get left behind if the code changes and the parameter is now used (as appears to be the case here).
it can backfire. Some compilers may treat this as invalid.
According to the C++ standard N3936 S5.4/11:
In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression. The expression is evaluated and its value is discarded.
A compiler would be entitled to observe that there is no side-effect and therefore this construct deserves at least a warning. According to #chris, MSVC is one of those compilers.

Expressions with no side effects in C++

See, what I don't get is, why should programs like the following be legal?
int main()
{
static const int i = 0;
i < i > i;
}
I mean, surely, nobody actually has any current programs that have expressions with no side effects in them, since that would be very pointless, and it would make parsing & compiling the language much easier. So why not just disallow them? What benefit does the language actually gain from allowing this kind of syntax?
Another example being like this:
int main() {
static const int i = 0;
int x = (i);
}
What is the actual benefit of such statements?
And things like the most vexing parse. Does anybody, ever, declare functions in the middle of other functions? I mean, we got rid of things like implicit function declaration, and things like that. Why not just get rid of them for C++0x?
Probably because banning then would make the specification more complex, which would make compilers more complex.
it would make parsing & compiling the
language much easier
I don't see how. Why is it easier to parse and compile i < i > i if you're required to issue a diagnostic, than it is to parse it if you're allowed to do anything you damn well please provided that the emitted code has no side-effects?
The Java compiler forbids unreachable code (as opposed to code with no effect), which is a mixed blessing for the programmer, and requires a little bit of extra work from the compiler than what a C++ compiler is actually required to do (basic block dependency analysis). Should C++ forbid unreachable code? Probably not. Even though C++ compilers certainly do enough optimization to identify unreachable basic blocks, in some cases they may do too much. Should if (foo) { ...} be an illegal unreachable block if foo is a false compile-time constant? What if it's not a compile-time constant, but the optimizer has figured out how to calculate the value, should it be legal and the compiler has to realise that the reason it's removing it is implementation-specific, so as not to give an error? More special cases.
nobody actually has any current
programs that have expressions with no
side effects in them
Loads. For example, if NDEBUG is true, then assert expands to a void expression with no effect. So that's yet more special cases needed in the compiler to permit some useless expressions, but not others.
The rationale, I believe, is that if it expanded to nothing then (a) compilers would end up throwing warnings for things like if (foo) assert(bar);, and (b) code like this would be legal in release but not in debug, which is just confusing:
assert(foo) // oops, forgot the semi-colon
foo.bar();
things like the most vexing parse
That's why it's called "vexing". It's a backward-compatibility issue really. If C++ now changed the meaning of those vexing parses, the meaning of existing code would change. Not much existing code, as you point out, but the C++ committee takes a fairly strong line on backward compatibility. If you want a language that changes every five minutes, use Perl ;-)
Anyway, it's too late now. Even if we had some great insight that the C++0x committee had missed, why some feature should be removed or incompatibly changed, they aren't going to break anything in the FCD unless the FCD is definitively in error.
Note that for all of your suggestions, any compiler could issue a warning for them (actually, I don't understand what your problem is with the second example, but certainly for useless expressions and for vexing parses in function bodies). If you're right that nobody does it deliberately, the warnings would cause no harm. If you're wrong that nobody does it deliberately, your stated case for removing them is incorrect. Warnings in popular compilers could pave the way for removing a feature, especially since the standard is authored largely by compiler-writers. The fact that we don't always get warnings for these things suggests to me that there's more to it than you think.
It's convenient sometimes to put useless statements into a program and compile it just to make sure they're legal - e.g. that the types involve can be resolved/matched etc.
Especially in generated code (macros as well as more elaborate external mechanisms, templates where Policies or types may introduce meaningless expansions in some no-op cases), having less special uncompilable cases to avoid keeps things simpler
There may be some temporarily commented code that removes the meaningful usage of a variable, but it could be a pain to have to similarly identify and comment all the variables that aren't used elsewhere.
While in your examples you show the variables being "int" immediately above the pointless usage, in practice the types may be much more complicated (e.g. operator<()) and whether the operations have side effects may even be unknown to the compiler (e.g. out-of-line functions), so any benefit's limited to simpler cases.
C++ needs a good reason to break backwards (and retained C) compatibility.
Why should doing nothing be treated as a special case? Furthermore, whilst the above cases are easy to spot, one could imagine far more complicated programs where it's not so easy to identify that there are no side effects.
As an iteration of the C++ standard, C++0x have to be backward compatible. Nobody can assert that the statements you wrote does not exist in some piece of critical software written/owned by, say, NASA or DoD.
Anyway regarding your very first example, the parser cannot assert that i is a static constant expression, and that i < i > i is a useless expression -- e.g. if i is a templated type, i < i > i is an "invalid variable declaration", not a "useless computation", and still not a parse error.
Maybe the operator was overloaded to have side effects like cout<<i; This is the reason why they cannot be removed now. On the other hand C# forbids non-assignment or method calls expresions to be used as statements and I believe this is a good thing as it makes the code more clear and semantically correct. However C# had the opportunity to forbid this from the very beginning which C++ does not.
Expressions with no side effects can turn up more often than you think in templated and macro code. If you've ever declared std::vector<int>, you've instantiated template code with no side effects. std::vector must destruct all its elements when releasing itself, in case you stored a class for type T. This requires, at some point, a statement similar to ptr->~T(); to invoke the destructor. int has no destructor though, so the call has no side effects and will be removed entirely by the optimizer. It's also likely it will be inside a loop, then the entire loop has no side effects, so the entire loop is removed by the optimizer.
So if you disallowed expressions with no side effects, std::vector<int> wouldn't work, for one.
Another common case is assert(a == b). In release builds you want these asserts to disappear - but you can't re-define them as an empty macro, otherwise statements like if (x) assert(a == b); suddenly put the next statement in to the if statement - a disaster! In this case assert(x) can be redefined as ((void)0), which is a statement that has no side effects. Now the if statement works correctly in release builds too - it just does nothing.
These are just two common cases. There are many more you probably don't know about. So, while expressions with no side effects seem redundant, they're actually functionally important. An optimizer will remove them entirely so there's no performance impact, too.

What does a "true;" or "10;" statement mean in C++ and how can it be used?

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.