37

In the 3.0.4 Linux kernel, mm/filemap.c has this line of code:

retval = retval ?: desc.error;

I've tried compiling a similar minimal test case with gcc -Wall and don't get any warnings; the behavior seems identical to:

retval = retval ? retval : desc.error;

Looking at the C99 standard, I can't figure out what formally describes this behavior. Why is this OK?

6
  • 9
    Have a look at stackoverflow.com/questions/2806255/…
    – vhallac
    Commented Oct 18, 2011 at 22:49
  • 3
    Thanks, vhallac. As far as I can tell, using this GCC extension is a tiny shortcut which completely destroys portability. Commented Oct 18, 2011 at 23:07
  • Exactly what I said to a colleague who tried to use it on one of our projects. :)
    – vhallac
    Commented Oct 18, 2011 at 23:13
  • Doesn't the Bourne shell have a construct like this too?
    – user354134
    Commented Oct 19, 2011 at 1:10
  • @ConradMeyer: You might be right, in some cases. However, the Linux kernel developers early on made a conscious decision to require gcc, and the kernel currently depends on several non-C99 extensions. See kernel.org/doc/Documentation/Changes for kernel dependencies, as well as en.wikipedia.org/wiki/Linux_kernel#Programming_languages.
    – Avi
    Commented Oct 19, 2011 at 10:59

4 Answers 4

36

As several others have said, this is a GCC extension, not part of any standard. You'll get a warning for it if you use the -pedantic switch.

The point of this extension is not really visible in this case, but imagine if instead it was

retval = foo() ?: desc.error;

With the extension, foo() is called only once. Without it, you have to introduce a temporary variable to avoid calling foo() twice.

8
  • 14
    but retval = foo(); retval = retval ? retval : desc.error; is MUCH better and is 100% portable.
    – akappa
    Commented Oct 18, 2011 at 23:00
  • I really liked David Given's response as well, but this one clarifies the single evaluation semantics and tells me about -pedantic causing a warning. Chosen. Commented Oct 18, 2011 at 23:05
  • 1
    @akappa: It's not better if you prefer to avoid introducing temporary variables. This is one of the really old extensions to GCC, and it reflects the functional-language tastes of GCC's original developers. Also, at the time, all local variable declarations had to be at the top of the function; "mixed declarations and code" wasn't standard till C99.
    – zwol
    Commented Oct 18, 2011 at 23:21
  • 1
    @Zack is there any document with the history of such obscure extensions? I would be interested in reading more about them, but I'm guessing its all buried in ancient logs from the GNU/GCC developer mailing lists.
    – crasic
    Commented Oct 19, 2011 at 1:27
  • 1
    @Zack: It might not have been a bad extension at the time, but that doesn't mean it isn't now.
    – Joren
    Commented Oct 19, 2011 at 9:56
20

It's a gcc extension. x ?: y is equivalent to x ? x : y --- see http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals.

Yes, I think it's evil too.

9
  • Why do you say it's evil? Nonportable, yes, but it has an effect you can't get any other way (see my answer).
    – zwol
    Commented Oct 18, 2011 at 22:57
  • 9
    @Zack: it's evil because it confuses people which doesn't know that non-portable and unnecessary syntax.
    – akappa
    Commented Oct 18, 2011 at 22:58
  • 3
    It's not that evil. It's kinda equivalent to C#'s ?? operator for nullable types. Commented Oct 19, 2011 at 8:22
  • 1
    @zzzzBov: ignorance of a GNU-specific C extension, that's the point.
    – akappa
    Commented Oct 19, 2011 at 9:32
  • 2
    @zzzzBov: I understand. I just wanted to make clear that I don't find it evil per se, but I find it evil because it is an extension which confuses people which does not know GNU C.
    – akappa
    Commented Oct 19, 2011 at 13:41
7

This is a GCC extension called Conditionals with Omitted Operands. Omitting the middle operand has the effect of using the value of the conditional as the omitted operand without evaluating it again. It is safe to use even if the conditional is a macro.

3

This is a gcc-specific extension to C and is not standard.

Not the answer you're looking for? Browse other questions tagged or ask your own question.