tags:

views:

471

answers:

9

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?

A: 

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);
kgiannakakis
A: 

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!

anon
+1  A: 

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.

Crashworks
+26  A: 

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 ;)

Magnus Hoff
Although usually you'll want to write (void)foo(); to show that you're explicitly / intentionally discarding the return value of foo().
Dan
@Dan: That's one theory, yes. I can count the number of times I've seen "(void)printf(...." on the fingers of one hand. (I do count on my fingers in binary, so it isn't quite as bad as it sounds.) You may have worked on projects that do that; I haven't.
David Thornley
+3  A: 

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.

Paolo Capriotti
In which case you suppress with "(void) result;" instead.
Steve Jessop
A: 

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.

RBerteig
+7  A: 

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.

Timbo
A: 

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;

James
A: 

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.

Howdy
I might need to be able to look the value of that variable in the debugger. Just excluding it and only leaving the function call is not an option in such case.
sharptooth