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.
The second expression will evaluate to either 1 or 0.
Quoting the C11 standard draft:
6.5.14 Logical OR operator
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
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.
No. The result type is int (or bool in C++), and will be either 1 or 0 (true or false in C++).
operator|| for pointers returns a bool, so ptr || default_ptr will evaluate to true if either ptr or default_ptr are non-null.
Related
Probably been answered, but could not find it.
In c++ what does
if(a=b)
mean?
versus
if(a==b)
I just spent two hours debugging to find that
if(a=b)
compiles as
a=b
Why does compiler not flag
if(a=b)
as an error?
In c++ what does if(a=b) mean?
a=b is an assignment expression. If the type of a is primitive, or if the assignment operator is generated by the compiler, then the effect of such assignment is that the value of a is modified to match b. Result of the assignment will be lvalue referring to a.
If the operator is user defined, then it can technically have any behaviour, but it is conventional to conform to the expectations by doing similar modification and return of the left operand.
The returned value is converted to bool which affects whether the following statement is executed.
versus
if(a==b)
a==b is an equality comparison expression. Nothing is assigned. If the types are primitive, or if the comparison operator is generated by the compiler, then the result will be true when the operands are equal and otherwise false.
If the operator is user defined, then it can technically have any behaviour, but it is conventional to conform to the expectations by doing similar equality comparison.
Why does compiler not flag
if(a=b)
as an error?
Because it is a well-formed expression (fragment) as long as a is assignable with b.
if(a=b) is a conventional pattern to express the operation of setting value of a variable, and having conditional behaviour depending on the new value.
Some compilers do optionally "flag" it with a warning.
Note that if you would assign value int a = 1 and you make an if statement
if (a = 2)
{
std::cout << "Hello World!" << std::endl;
}
It still works, even though they are two different values, they will do the std::cout
However if you use a double equals sign == it will not.
The reason for this is if you use the standard double equals sign == you are asking the code if a is equivalent to 2, if it is 2. Obviously it's not, so it doesn't std::cout. But if you use an equals sign, you are changing the value a to 2, so it continues with the if statement.
And, to prove this, try taking away the int a = 1 from before the if statement and add an int before a in the if statement, it works.
This question already has answers here:
Is Short Circuit Evaluation guaranteed In C++ as it is in Java?
(2 answers)
Closed 7 years ago.
Suppose I have two expressions left/right of || operator. I find if left expression is true, the right operator will never be called. For example, in my below code, when getRand returns true, I found Foo will never be called. I tested on XCode on Mac OSX, and wondering if it is a reliable feature of C++ we could rely on -- if left part of || is true, right part will never be called, or it is a special feature just for specific platform (e.g. OSX with XCode)? Post my code below, thanks.
bool Foo()
{
std::cout << "I am called!\n";
return false;
}
bool getRand()
{
int random_variable = std::rand();
std::cout << random_variable << '\n';
return random_variable % 2 == 1;
}
int main(int argc, const char * argv[]) {
if (getRand() || Foo())
{
std::cout<<"Hello World \n";
}
return 0;
}
thanks in advance,
Lin
Yes, it is a guaranteed feature called short circuit evaluation.
Likewise, an expression false && expression will never evaluate the right expression.
wondering if it is a reliable feature of C++ we could rely on -- if left part of || is true, right part will never be called?
Yes, for builtin operator.
From the standard, $5.15/1 Logical OR operator [expr.log.or] (bold by me)
The || operator groups left-to-right. The operands are both
contextually converted to bool (Clause 4). It returns true if either
of its operands is true, and false otherwise. Unlike |, || guarantees
left-to-right evaluation; moreover, the second operand is not
evaluated if the first operand evaluates to true.
And note that the overload of operator|| will lose this special property.
Logical operators (bold by me)
Builtin operators && and || perform short-circuit evaluation (do not
evaluate the second operand if the result is known after evaluating
the first), but overloaded operators behave like regular function
calls and always evaluate both operands.
Since its one choice or another there is no need for the second part to be evaluated, is not platform dependant is a language feature.
Recently I have read some chapters C++ Primer, there is one things which made me confused.
The book says:
There are four operators that do guarantee the order in which operands are evaluated.
the logical AND (&&) operator,
the logical OR (||) operator,
the conditional (? :) operator,
and the comma (,) operator.
And then I saw these codes:
if (val == true) { /* ... */ } // true only if val is equal to 1!
Then the book explain:
If val is not a bool, then true is converted to the type of val before the == operator is applied.
That is, when val is not a bool, it is as if we had written
if (val == 1) { /* ... */ }
Here is my question:
Why is the bool type true converted to arithmetic type, not the val instead? Is it involve the order of evaluation of equality operator?
Just as the book says only four operators guarantee the order, not including equality operator. So the result of the expression above should be undefined, am I right? If not, what it should be?
Looking forward to your reply. Thanks in advance.
It has nothing to do with the order of evaluation. The comparison operators always perform the usual arithmetic conversions on their operands. These conversions apply equally to both operands (although the order is unspecified). In the case in which a bool is being compared to another integral type, the operand of type bool is always promoted to int first.
Relational operators such as ==, <=, etc., always produce boolean results. This is part of a set of rules known as "the usual arithmetic conversions".
Which side of the operator gets converted to what and in what order is somewhat esoteric and would concern compiler writers. It would be beyond the scope of a programmer.
In the condition of the if statement there are two different types
These are:
int
bool
In c++ types such as:
bool
char
short
are always converted to int first, hence in the condition of the if, true which is bool is converted to int and is 1 i.e, true is 1 and
val remains the same.
In C conditional-oriented operators evaluate to either 1 or 0 of type int (even if it does have dedicated _Bool type). Referring to C11 N1570 draft:
C11 §6.5.8/6 Relational operators
Each of the operators < (less than), > (greater than), <= (less than
or equal to), and >= (greater than or equal to) shall yield 1 if the
specified relation is true and 0 if it is false.107) The result has
type int.
C11 §6.5.9/3 Equality operators
The == (equal to) and != (not equal to) operators are analogous to the
relational operators except for their lower precedence.108) Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. For any pair of operands, exactly
one of the relations is true.
C11 6.5.13/3 Logical AND operator
The && operator shall yield 1 if both of its operands compare unequal
to 0; otherwise, it yields 0. The result has type int.
C11 6.5.14/3 Logical OR operator
The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
As I checked C++ seems to be different in this matter, as in following example (see http://ideone.com/u3NxfW):
#include <iostream>
#include <typeinfo>
int main() {
double x = 10.0;
std::cout << typeid(x <= 10.0).name() << std::endl;
return 0;
}
outputs b, which as I guess indicates bool type. Does C++ guarantee that all of these operators always evaluate to bool type (in contrast to C)?
No, because of operator overloading. This has been mentioned before, but I can give the real life example of expression templates. The idea, generally, is to allow writing "lazy" expressions (that is, really, function objects or ASTs) with syntax that is very similar to the normal, eager use of logical operators. Typically, many other operators, in particular arithmetic operators are also, overloaded.
For instance, one design goal of Boost.Lambda was to simplify the use of algorithms:
std::string str;
// ...
std:.string::iterator firstA = std::find_if(str.begin(), str.end(), _1 == 'a' || _1 == 'A');
Previously, in "pure" C++98, it was generally necessary to write numerous named functions or function objects before many standard algorithms could be used effectively.
Since C++11, Boost.Lambda is not as useful any more since lambda expressions have been added to the core language. There are still numerous EDSLs (embedded domain-specific languages) where C++11 lambdas cannot replace expression templates though, e.g. you may want to generate SQL command strings directly from a C++ EDSL in a way similar to LINQ in .NET, but as a portable library solution. Another example: the VexCL library uses expression templates to generate GPU kernels.
This is probably the only legitimate use of non-bool return types for overloaded logical operators, but it's not generally considered esoteric.
Contrary to C, in C++, relational operators, equality operators and logical operators (logical AND, logical OR and logical negation) all yield a value of type bool.
For example:
(C++11, 5.9p1 Relational operators) "[...] The type of the result is bool."
EDIT: for the sake of completeness, all the operators listed above can be overloaded and thus the resulting type can be changed. See Arne Vogel answer for real life example.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Safety concerns about short circuit evaluation
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
E.g.:
Foo* p;
//....
if ( p && p->f() )
{
//do something
}
is the f() guaranteed not to be called if p == NULL?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Might the optimizer change something like:
int x;
Foo* p;
//...
if ( p->doSomethingReallyExpensive() && x == 3 )
{
//....
}
to a form where it evaluates x==3 first? Or will it always execute the really expensive function first?
I know that on most compilers (probably all) evaluation stops after the first false is encountered, but what does the standard say about it?
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Yes. That is called short-circuiting.
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Yes. From left to right. The operand before which the expression short-circuited doesn't get evaluated.
int a = 0;
int b = 10;
if ( a != 0 && (b=100)) {}
cout << b << endl; //prints 10, not 100
In fact, the above two points are the keypoint in my solution here:
Find maximum of three number in C without using conditional statement and ternary operator
In the ANSI C standard 3.3.13:
Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; there is a sequence point after the
evaluation of the first operand. If the first operand compares equal
to 0, the second operand is not evaluated.
There is an equivalent statement in the C++ standard
&& (and ||) establish sequence points. So the expression on the left-hand side will get evaluated before the right-hand side. Also, yes, if the left-hand side is false/true (for &&/||), the right-hand side is not evaluated.
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
5.14/1. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
This only works for the standard && operator, user defined overloads of operator && don't have this guarantee, they behave like regular function call semantics.
Might the optimizer change something like:
if ( p->doSomethingReallyExpensive() && x == 3 )
to a form where it evaluates x==3 first?
An optimizer may decide to evaluate x == 3 first since it is an expression with no side-effects associated if x is not modified by p->doSomethingReallyExpensive(), or even evaluate it after p->doSomethingReallyExpensive() already returned false. However, the visible behavior is guaranteed to be the previously specified: Left to right evaluation and short-circuit. That means that while x == 3 may be evaluated first and return false the implementation still has to evaluate p->doSomethingReallyExpensive().