10

Is it safe to shorten this usage of the ternary operator:

process_ptr(ptr ? ptr : default_ptr);

with the short-circuit:

process_ptr(ptr || default_ptr);

in C and C++? In other words, are we guaranteed to get either ptr or default_ptr back from the experssion, or is it perhaps allowed for the expression to result in an arbitrary "logical true" value, if the expression is logically true?

This is the kind of code you'd see all over Perl code, but I rarely see it in C/C++, that's the original basis of my question.

Irfy
  • 9,323
  • 1
  • 45
  • 67

4 Answers4

11

The second expression will evaluate to either 1 or 0.

Quoting the C11 standard draft:

6.5.14 Logical OR operator

  1. The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

So the two expressions are very different, since one of them yields a pointer, and the other one an integer.

Edit:

One of the comments claims that this answer is only valid for c, and @Lightness Races in Orbit is right.

There are also answers that are only correct for c++1, although the only difference with them is that c++ has type bool and then it evaluates this expression as bool instead of int. But apparently there is an important issue with overloading || operator in c++, which prvents short-citcuiting to apply for the object that overloads it.

So for c++ there are more things to consider, but since this question was tagged with both languages tags, then it's necessary to mention at least the differece.

The rule still applies when short-circuiting applies, i.e. the result of the evaluation of the expressions is either 1 or 0 for c and true or false for c++.


1 Like these answers: 1, 2

Community
  • 1
  • 1
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 2
    The edit to your answer doesn't make sense, I think because you misquoted @LightnessRacesinOrbit as claiming the answer is only valid in C++ (which makes the second paragraph seem confusing and contradictory). Additionally, I don't see the point of the link to the YouTube flame-bait claiming that C and C++ should be one language. – Josh Darnell Jun 03 '15 at 18:07
  • @jadarnel27 The link to the video, is just to note that even though c and c++ are not the same languages c++ tries to be as much as possible like c, because the original intention of the creator was to make it one language. – Iharob Al Asimi Jun 03 '15 at 18:32
  • 2
    @jadarnel27: It's also misleading/wrong because it suggests that the only difference between C and C++ is the type of the expression when, in fact, short-circuiting — ostensibly the very point of this question — only works on built-in boolean operators. [Once you overload them, a C++ feature, that goes away](http://stackoverflow.com/a/628554/560648). I probably wouldn't have bothered commenting otherwise. Thus, the answer is still sort of wrong. That said, despite the title, it's difficult to see where short-circuiting _really_ fits into this question. – Lightness Races in Orbit Jun 04 '15 at 00:33
  • @LightnessRacesinOrbit I see your point, you're right, and that's one of the reasons why I don't like c++, it's so complicated. – Iharob Al Asimi Jun 04 '15 at 00:47
  • @iharob: It really is awful :) – Lightness Races in Orbit Jun 04 '15 at 11:47
5

Concerning the Perl style, which usually is of type

do_someting || die("didn't work")

This would work in C++ also.

function_returning_bool(some) || std::cout << "Error!" << std::endl;

This is due to the || being a logical OR operator and causing the short-circuit in this case if the return value is true.

But using it instead of the ternary operator is impossible.

std::cout << ("asd" || "dsa");

This will result in 1 being output.

Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74
  • 1
    Nitpick, if the return value from `function_returning_bool()` is a class with an overridden `operator||()` method, then short-circuiting won't happen.... – Andre Kostur Jun 03 '15 at 14:00
  • @AndreKostur Thanks, forgot about that. I always appreciate nitpicking :) – Sami Kuhmonen Jun 03 '15 at 14:01
  • Obviously, it's a matter of taste whether `condition() || exec_on_false()` is good style. I'd rather say it isn't: since the result is boolean, you can pretty much only use it for side-effect-only functions, and for these you might as well use an `if`, which is much clearer. – leftaroundabout Jun 03 '15 at 22:24
3

No. The result type is int (or bool in C++), and will be either 1 or 0 (true or false in C++).

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
3

operator|| for pointers returns a bool, so ptr || default_ptr will evaluate to true if either ptr or default_ptr are non-null.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193