15

Is there any difference in below two castings ?

int a=10;
int *p=&a;

(void)p;          //does not give any warning or error 

or

(void *)p;        //error: statement with no effect [-Werror=unused-value]

when complied with gcc -Wall -Werror --std=c99 -pedantic

Just saw that in this answer. (clearly I misunderstood something )

Community
  • 1
  • 1
ameyCU
  • 16,489
  • 2
  • 26
  • 41

2 Answers2

15

When you do

(void) p;

You tell the compiler to simply disregard the result of the expression p. It's effectively the same as an empty statement:

;

When you do

(void *) p;

You tell the compiler to treat the variable p as a generic pointer, and that's the full expression for the statement, an expression which doesn't really do anything and you get the error message.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • can you give some real-world-use of this feature? – David Haim Oct 14 '15 at 14:47
  • 1
    @DavidHaim: I've seen it in cases where certain local variables are only used inside an `IFDEF`, to make it so that it doesn't raise warnings when compiled with settings that take the `ELSE` branch. – Mason Wheeler Oct 14 '15 at 15:02
  • lol, so declare the local variable inside the ELSE branch if it's the only place that touches it. or I guess it's commping from a period where you ahd to declare all the variables together at the start of the scope.. – David Haim Oct 14 '15 at 15:17
  • "It's effectively the same as an empty statement" -> pretty much any expression in C can have side effects. This answer currently implies that a compiler might reduce `(void)sideEffectingFunction(a = b, c++);` down to `;`, which is obviously not the case. – Alex Celeste Oct 14 '15 at 15:34
  • @Leushenko Of course it's not the *general* case, but for *this* case it's basically equivalent. – Some programmer dude Oct 14 '15 at 16:12
  • 2
    @DavidHaim Casting a variable to `void` is a way to silence potential compiler warnings about unused function arguments. – Some programmer dude Oct 14 '15 at 16:13
  • @DavidHaim ↑ That can be seen as an example [here](http://stackoverflow.com/a/28382691/3049655) – Spikatrix Oct 16 '15 at 14:05
14

Yes, obviously.

 (void)p;

means the object is getting casted to void type, (which is not a complete type) and that being the complete expression, the result of the expression should not be used, hence compiler does not check for it's usage.

Quoting C11 standard, chapter 6.3.2.2, void

The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way,[......] If an expression of any other type is evaluated as a void expression, its value or designator is discarded.

So, no warning or error is generated.

OTOH,

(void *)p;

means the object is a pointer to void type, which is a complete type and should be used in your program. In that case, the non-usage of the object out of the expression is rightly reported by the compiler.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • With the former casting value at address pointed by `p`, does that have any change ? – ameyCU Oct 14 '15 at 14:35
  • @ameyCU nopes. Only if there is s side effect, that will make effect, which is not the case here. – Sourav Ghosh Oct 14 '15 at 14:36
  • And casting `p` again to `int *` will be safe ? – ameyCU Oct 14 '15 at 14:38
  • @ameyCU yes, it will, but you won't be needing that. – Sourav Ghosh Oct 14 '15 at 14:41
  • Why would I not need that ? Because I am casting to `void` in first place ? – ameyCU Oct 14 '15 at 14:42
  • @ameyCU but did you store it anywhere? :) – Sourav Ghosh Oct 14 '15 at 14:43
  • then why should have it any effect on `p` itself? :) – Sourav Ghosh Oct 14 '15 at 14:45
  • To elaborate, the supression of that sort of warning is largely what casts to void are for. In this specific example, the statement is indistinguishable from the empty expression, but in other cases there may be side-effects. Casting to void is a way to inform the compiler that while you may care about the side-effects, you don't care about the expession's value. e.g. printf("Foo\n") evaluates to 4 (the number of characters printed) if it is successful, or a negative value otherwise. (void)printf("Foo\n") just prints Foo\n as best it can and doesn't evaluate to anything. – Ray Oct 14 '15 at 22:15