views:

351

answers:

5

In the Android open-source qemu code I ran across this line of code:

machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */

It this just a confusing way of saying:

if (machine->max_cpus) {
   ; //do nothing
} else {
 machine->max_cpus = 1;
}

If so, wouldn't it be clearer as:

if (machine->max_cpus == 0) machine->max_cpus = 1;

Interestingly, this compiles and works fine with gcc, but doesn't compile on http://www.comeaucomputing.com/tryitout/ .

+2  A: 

The K&R BNF shows an expression is required between "?" and ":". I don't think gcc should be compiling that without a diagnostic.

Larry Engholm
It's a non-standard gcc extension I believe. Best avoided.
Paul R
+17  A: 

This is permitted in GNU as an obscure extension to C

5.7 Conditionals with Omitted Operands

The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.

Therefore, the expression

 x ? : y

has the value of x if that is nonzero; otherwise, the value of y.

This example is perfectly equivalent to

 x ? x : y

In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.

As you can probably guess, avoiding this is recommended for readability and portability reasons. I'm honestly surprised to see such a grammar-incompatible extension to C.

Uri
Interesting. This seems both incredibly useful as a syntactic feature, and incredibly obscure to understand.
quixoto
I agree. But there are many things one could add to C to make it more elegant, I'm surprise a compiler vendor would explicitly make such a permissive change to the C grammar. If this was C++, that's another story since it used to be a jungle of incompatibility.
Uri
Hey, that's how `||` is supposed to work.
Potatoswatter
interresting. that became ?? in C# "x if x is not null, otherwise y" => c ?? y
Stephane
@Potatoswatter: not really, since presumably `max_cpus` is not boolean valued. `||` has no way of evaluating to `3` if the prior value was `3`.
Steve Jessop
+3  A: 

This is a GCC extension that means "if the condition is true, use it, else use this other value", so

machine->max_cpus = machine->max_cpus ?: 1;

is shorthand for

machine->max_cpus = machine->max_cpus ? machine->max_cpus : 1;

although if the conditional has side-effects, it will only be run once

Michael Mrozek
+1  A: 

It's a GCC extension, and it gets more interesting and useful when the condition has side effects.

In this case, yes, I for one would agree it's obscure more than anything else.

John Marshall
+2  A: 

Using gcc's -pedantic flag, it does say

foo.c:5: warning: ISO C forbids omitting the middle term of a ?: expression

Larry Engholm