I had the need to code a statement of the form
a = a || expr;
where expr should be evaluated and the result be assigned to a iff a is not set. this relies on the logical OR's short-circuiting capabilities.
The shorter way to write the above would, of course, be
a ||= expr;
but (to my surprise) C does not have logical assignment operators.
So my question is twofold. First, is there a shorter way to write the first statement in standard C (the ternary operator is even worse - a = a ? a : expr requires me to spell out a thrice).
Secondly, why aren't there logical assignments in C? The possible reasons I could think of are:
it makes the grammar harder to parse?
there is some subtlety in handling short-circuiting for these cases?
it was considered superfluous (but isn't that an argument against ALL the operator assignments?)
EDIT
Please unlock this question because:
The question it has been linked to (as a alleged duplicate of) HAS NOT BEEN ANSWERED. The (accepted) answer to that question states that ||= is not present because duplicates the functionality of |=. That is the wrong answer. |= does not short-circuit.
C and C++ are NOT the same languages. I wish to know why C doesn't have it. In fact, the fact that derived languages like C++ and, particularly, Java (which did not suffer from the problems of legacy code as has been suggested in Edmund's answer) makes the question even more interesting.
EDIT 2
It now seems like my original intent was wrong. In the statement a = a || expr (where a is integral and expr returns an integral value, first both a and expr will be implicitly converted to "booleans", and then the "boolean" value will be assigned to a. This will be incorrect — the integral value will be lost. Thanks, Jens and Edmund.
So for the first part of the question, the correct ways, not alternatives :), to code my intention would be:
if (!a) a = expr;
or
a = a ? a : expr;
they should be optimized the same (I think) though personally I would prefer the first one (because it has one less a to type).
However, the second part of the question still remains. The arguments that Jens and Edmund about have given about the ambiguity in a ||= expr apply equally well to a = a || expr. the assignment case can simply be treated as the normal one:
convert a to boolean
if it is true, the value of the entire expression becomes equal to the boolean value of a
otherwise evaluate expr, convert result to boolean, assign to a, and return it
The steps above seem to be the same for both the assignment and normal case.
a ||= expr is problematic due to short circuit evaluation of its equivalent a = a || expr.
To have a ||= expr function like a = a || expr consider OP's assertion:
"In the statement a = a || expr ..., first both a and expr will be implicitly converted to "booleans","
This is not quite correct. expr will not be converted if a evaluates to true. This would make a difference should expr be something like scanf() or rand() or some function that affected the state of the program.
Code such as a ||= scanf("%d", &i) != 1; would only attempt to scan data with a false value in a. Although it would be possible to extend the language this way, additional short-circuit operators to the current set of || and && would likely cause more coding problems than clear simplifications.
On the other hand: A quick, if obfuscated, way to write code where functions return non-zero codes on error.
// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2(); // Only valid if C was extended with &&=
error &&= foo3();
Because the return type of operators || and && is not the same as type of their left argument.
The return type of || and && is always int1, while the left argument may be any integral, floating point or pointer type. The operands also don't have to be of the same type. Therefore defining x ||= y as x = x || y and x &&= y as x = x && y as would be consistent with other augmented assignments would not be able to store the result in the argument for most types.
You could come up with other definitions, e.g. x ||= y as if(!x) x = y and x &&= y as if(!y) x = y, but that would not be exactly obvious and it is not that useful, so it was not included.
1In C++ it is bool.
I guess the simple answer is that || is a boolean operator: and in C, a "boolean" is 0 or 1. The operands are implicitly converted to booleans (I have not checked that that's what the spec actually says, but it's how C behaves), and the result is a boolean.
Altering the semantics to support this pattern may well be feasible -- until someone relies on || doing what it's always done.
I cannot find any particular reason, why the operators don't exist (in C99).
So the only reason I can find is, that there was no boolean type in C89, and those boolean operators were intended to be solely used in if's.
Example:
int i = 5;
/* This should not make any difference,
since or'ing with false, shouldn't change
the value... dib di dib diddy...*/
i ||= 0; /* Actually: i = i || 0, which gives 'true' */
i is now '1'', which for most people is pretty counter intuitive.
This operator obviously doesn't bring any clearence or coding improvement without the boolean type, that would make sence being or'd with another one.
In my opinion, the implementation of a ||= b; as if(!a) a = b; would be pretty straightforward and has aleardy been implemented by e.g. Lua.
So you're question seems to be a bit, why C has been designed the way it has been designed.
If this question was about C++, you could for example ask Bjarne Stroustrup and ask him, what had went into him. Since this is not the case, this seems to me to be kind of a dead end, because the standard has been written quite some time ago and you cannot really ask people anymore, why the h***.
On the other hand, this incomplete operator set should (in my opinion) aleardy have been made whole using a similar notation than yours, since in my opinion, there is no reason against it.
I hope I could help a little.
One simple explanation is this.
bool resultsComputeAll = false;
bool resultsUntilFirst = false;
for (int i = 0; i < 10; ++i) {
resultsComputeAll = compute(i) || resultsComputeAll;
resultsUntilFirst = resultsUntilFirst || compute(i);
}
Which one would be result ||= compute(i)? It's ambiguous so it's better to not define.
Related
I am a getting warning:
warning: '<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]
for the code similar to the following:
int a=7,b=3;
int index=((a<<1)||b)&&5;
To explain the rationale behind such warnings:
C did get a boolean type _Bool/bool as per C99, but no changes were done to the behavior of the various logical operators of the language. That is:
Equality operators ==/!=
Relational operators <,<=,>,>=
Logical AND &&
Logical OR ||
Logical negation !.
Despite C having a boolean type, all of these operators return type int with value 1 or 0. Unlike C++ where all of these operators actually return type bool with value true/false. This is a known flaw of C.
It's common good practice however to treat such expressions as if they were boolean. Coding guidelines like MISRA C encourage the use of a fictional type "essentially boolean", meaning any expression that could be treated as _Bool. The reason for this is that it makes code more self-documenting and also makes it harder to create various typo-related bugs.
For example if(str) could mean check for NULL, or it could mean check for null termination but oops we forgot to dereference. Same thing with if(*str). Whereas if we only pass the result of a logical operator to if, the code becomes much clearer and it becomes harders to write bugs: if(str != NULL) could only mean check for NULL and if(*str != '\0') could only mean check for null termination.
In your case, the || operator only cares if the operands are zero or non-zero ("essentially boolean"). In case a is non-zero then a<<1 will not change that. In case a is zero, then a<<1 is zero as well. Since the result is passed on to a logical operator, "in a boolean context", the shift is pointless - hence the warning. But of course a<<1 might take all kinds of other values in another context such as for example if(a<<1 & mask).
It would be reasonable to strongly suspect that you actually meant to write a<1 instead. Because that would yield either 0 or 1, where < is also a logical operator like ||.
I got the solution. We should avoid integers using with logical operators (eg. ||,&&). Using integers with bitwise operators (eg. <<,&,|,etc.) is fine.
Sometimes we don't get this problem while running on compilers because of low priority warning filters. In complex and warning sensitive compilers it comes up.
Thanks
I have a small C function to convert Fortran
baralign(n, b) {
return ((n&~(~0<<b)) ? (n&(~0<<b))+(1<<b):(n))
}
I wrote the condition in above statement as follows in Fortran
if (IAND(n,NOT(ISHFT(NOT(0),b))))
I am not sure about this condition. When I run this code, it makes an error saying
IF clause requires a scalar LOGICAL expression.
The problem is related to question Implicit conversion integer <--> logical in Fortran if statement , however that question is slightly different because the asker there is aware of the nature of the problem.
You cannot put an integer expression into an if condition in Fortran as you do in C
integer :: n, b
if (IAND(n,NOT(ISHFT(NOT(0),b))))
is not possible. The condition must be a logical expression.
If it should be true for any non-zero value of the integer expression, then you must put there an integer comparison
if (IAND(n,NOT(ISHFT(NOT(0),b))) /= 0) then
If you require the expression to be exactly 1, you could use == 1 instead.
The rest will likely be
baralign = IAND(n,ISHFT(NOT(0),b)) + ISHFT(1, b)
else
baralign = n
end if
but I don't know the purpose of the code so I can't be sure.
I was reading my textbook for my computer architecture class and I came across this statement.
A second important distinction between the logical operators '&&' and '||' versus their bit-level counterparts '&' and '|' is that the logical operators do not evaluate their second argument if the result of the expression can be determined by evaluating the first argument. Thus, for example, the expression a && 5/a will never cause a division by zero, and the expression p && *p++ will never cause the dereferencing of a null pointer. (Computer Systems: A Programmer's Perspective by Bryant and O'Hallaron, 3rd Edition, p. 57)
My question is why do logical operators in C behave like that? Using the author's example of a && 5/a, wouldn't C need to evaluate the whole expression because && requires both predicates to be true? Without loss of generality, my same question applies to his second example.
Short-circuiting is a performance enhancement that happens to be useful for other purposes.
You say "wouldn't C need to evaluate the whole expression because && requires both predicates to be true?" But think about it. If the left hand side of the && is false, does it matter what the right hand side evaluates to? false && true or false && false, the result is the same: false.
So when the left hand side of an && is determined to be false, or the left hand side of a || is determined to be true, the value on the right doesn't matter, and can be skipped. This makes the code faster by removing the need to evaluate a potentially expensive second test. Imagine if the right-hand side called a function that scanned a whole file for a given string? Wouldn't you want that test skipped if the first test meant you already knew the combined answer?
C decided to go beyond guaranteeing short-circuiting to guaranteeing order of evaluation because it means safety tests like the one you provide are possible. As long as the tests are idempotent, or the side-effects are intended to occur only when not short-circuited, this feature is desirable.
A typical example is a null-pointer check:
if(ptr != NULL && ptr->value) {
....
}
Without short-circuit-evaluation, this would cause an error when the null-pointer is dereferenced.
The program first checks the left part ptr != NULL. If this evaluates to false, it does not have to evaluate the second part, because it is already clear that the result will be false.
In the expression X && Y, if X is evaluated to false, then we know that X && Y will always be false, whatever is the value of Y. Therefore, there is no need to evaluate Y.
This trick is used in your example to avoid a division by 0. If a is evaluated to false (i.e. a == 0), then we do not evaluate 5/a.
It can also save a lot of time. For instance, when evaluating f() && g(), if the call to g() is expensive and if f() returns false, not evaluating g() is a nice feature.
wouldn't C need to evaluate the whole expression because && requires both predicates to be true?
Answer: No. Why work more when the answer is known "already"?
As per the definition of the logical AND operator, quoting C11, chapter §6.5.14
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0.
Following that analogy, for an expression of the form a && b, in case a evaluates to FALSE, irrespective of the evaluated result of b, the result will be FALSE. No need to waste machine cycle checking the b and then returning FALSE, anyway.
Same goes for logical OR operator, too, in case the first argument evaluates to TRUE, the return value condition is already found, and no need to evaluate the second argument.
It's just the rule and is extremely useful. Perhaps that's why it's the rule. It means we can write clearer code. An alternative - using if statements would produce much more verbose code since you can't use if statements directly within expressions.
You already give one example. Another is something like if (a && b / a) to prevent integer division by zero, the behaviour of which is undefined in C. That's what the author is guarding themselves from in writing a && 5/a.
Very occasionally if you do always need both arguments evaluated (perhaps they call functions with side effects), you can always use & and |.
How to get rid of MISRA violation on following statement
typedef unsigned char boolean;
boolean A, B;
A = !B;
Operand of logical ! operator is not an 'effectively Boolean'
expression. MISRA-C:2004 Rule 12.6; REFERENCE - ISO:C90-6.3.3.3 Unary
Arithmetic Operators
If you read rule 12.6 it says "check Boolean Expressions" in the appendix. There we can read
"Boolean-by-enforcement values can be introduced by implementing a specific type enforcement mechanism using a tool. A Boolean type could be associated with a specific typedef, and would
then be used for any objects that are Boolean. This could bring many
benefts, especially if the checking tool can support it, and in
particular it could help avoid confusion between logical operations
and integer operations."
MISRA-C:2004 assumes C90, and in C90 there is no bool type, you have to typedef it yourself, like you have done. Since your intention is to have a type which is effectively boolean, the code is just fine. In fact, your code follows MISRA recommendations beyond the mandatory ones.
The problem lies with your tool: it either does not support to allow a specific boolean type as per MISRA recommendations, or it is misconfigured.
Simple... don't use ! on things that aren't booleans. Just because your typedef is named boolean doesn't mean it is; it's still an unsigned char.
You could write:
if (b == 0) A = 1;
else A = 0;
I don't think MISRA allows ternary operators (could be wrong; not an expert) but if it does, you could write:
A = (b == 0) ? 1 : 0;
How about this:
A = (B == 0 ? 1 : 0);
Have you tried the idiom !! to convert values in boolean:
bool bool_val = !!int_val;
Then the far-fetched following code might work:
A = !(!!B) // B is "cast" within the parenthesis then we apply the "NOT"
Though the ISO:C90 standard says the operand can be of any scalar type the ! operator always yield a value of either 0 or 1; the underlying type (in MISRA-C:2004 terms) is considered effectively boolean, but the operand is not. Since the operator interprets its operand in a Boolean sense by comparing it 0 with try:
A = (B==0);
which make the logical comparison explicit. Also, depending on the tool, there may a boolean type enforcement mechanism you can configure for this typedef.
I have been using ! (logical negation) in C and in other languages, I am curious does anyone know how to make your own ! function? or have a creative way of making one?
int my_negate(int x)
{
return x == 0 ? 1 : 0;
}
!e can be replaced by ((e)?0:1)
Remember the bang operator '!' or exclamation mark in english parlance, is built into the programming language as a means to negate.
Consider this ternary operator example:
(some condition) ? true : false;
Now, if that was negated, the ternary operator would be this
(some condition) ? false : true;
The common area where that can get some programmers in a bit of a fit is the strcmp function, which returns 0 for the strings being the same, and 1 for two strings not the same:
if (strcmp(foo, "foo")){
}
When really it should be:
if (!strcmp(foo, "foo")){
}
In general when you negate, it is the opposite as shown in the ternary operator example...
Hope this helps.
C considers all non-zero values "true" and zero "false". Logical negation is done by checking against zero. If the input is exactly zero, output a non-zero value; otherwise, output zero. In code, you can write this as (input == 0) ? 1 : 0 (or you can convert it into an if statement).
When you ask how to "make your own ! method", do you mean you want to write a function that negates a logic value or do you want to define what the exclamation-point operator does? If the former, then the statement I posted above should suffice. If the latter, then I'm afraid this is something that can't be done in C. C++ supports operator overloading, and if doing this is a strict necessity then I would suggest looking there.
If you want to overload an operator, the proper prototype is:
bool operator!();
I'm not a big fan of overloading operators, but some people like their syntactic sugar.
EDIT: This is C++ only! Put it in the definition of your class.