What double negation does in C - c

I had a controversy about what compilers "think" about this:
a = 8;
b = !!a;
So, is b == 0x01 ? Is TRUE always 0x01 or it may be 0xFF, 0xFFFF, 0xFFFFFFFF etc..?
If I want to extract only 0x00 if (a == 0) and 0x01 if (a > 0) does this double negation approach works?
In other words: to obtain result only 0 or 1, what is better to use?
a) a>0?1:0;
b) !!a
I hope you understand my question.

You have not supplied enough information to tell whether !!a works for your purposes or not.
You stated that you really need the result of a > 0. However, this is not equivalent to !!a if a is signed and holds a negative value. If this is possible, then the answer is obviously "no".
!!a is equivalent to a != 0, not to a > 0.

Yes, b == 1. The result of any boolean operator is always 0 or 1. You can do better though...
I want to extract only 0x00 if (a == 0) and 0x01 if (a > 0)
b = a > 0; most accurately reflect your rule.

!!a will be either 0 or 1, and will be type int. It will be 0 for zero a, and 1 otherwise.
As for your choices (a) and (b), they are not equivalent, due to a possibility of a being negative. That aside, you could argue that a > 0 ? 1 : 0 is clearer but in performance-critical applications !!a may be better as it will not branch whereas a ternary conditional could dump the pipeline. But a good compiler will optimise out either way. I seldom use either since things like if (a) and if (!!a) are functionally equivalent.

The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E). C11 §6.5.3.3 5
b below will typical have the value of 1 (or possible -1, see below).
a = 8;
b = !!a;
So, is b == 0x01?
Yes (* see below)
Is TRUE always 0x01 or it may be 0xFF, 0xFFFF, 0xFFFFFFFF etc..?
In <stdbool.h>, true is a macro with the integer constant 1. TRUE is not defined by the C standard. Various implementations defines it with the value of 1. It might be have other values. It certainly should be non-zero.
what is better to use?
A) a>0?1:0
B) !!a
Both result in an int with the value of 0 or 1. A reasonable to good compiler would be expected to generate the same code for both (if a in not signed). Use the form that 1) adhere to your groups coding standard or else 2) best conveys the meaning of code at that point. A third option which results in type (bool):
C) (bool) a
If a is signed , then a>0?1:0 is not equivalent to !!a. a != 0 ? 1 :0 is equivalent of !!a.
* If b is a 1 bit signed bit field, b = !!8 will have the value of -1.

In teems of speed I think this is highly dependent on the compiler and processor you are using.
The longer expression would produce an executable 4 - 16 bytes larger.

Related

Using Logical AND 1 when setting a variable in C

While looking through some code today, I came across an interesting(unecessary?) method for setting a variable: Adding a logical AND to the value.
LED_GRN = (ivLEDGrnSequence & ivLEDSlot) && 1;
I looked around a bit more for some of these occurrences and found them throughout the code, but in different forms:
As an argument for a function:
isoAgCmdHideShow(iObjectID,( (ecu.l & sVar->mask) && 1), (uint8_t *)TxMsg.buf);
In a conditional:
if( (usbQueue.selection & USB_SELECTION_CAN_1) && 1 ) {return TRUE;}
Does this extra logical AND actually change anything about the code, or is it just superfluous? I tried searching for this online, but the closest I found to an answer is Short-Circuit Evaluation which doesn't seem to apply in these situations because short-circuiting a 1 is useless.
In short, what does Logical AND 1 do for variable declaration?
This appears to be a trick to force any non-zero number to 1, while keeping zeros - alongside a more common !!(expr) idiomatic construct.
The idea is to set LED_GRN to 1 or 0 based on the value of ivLEDGrnSequence & ivLEDSlot.
Other ways to do the same thing are as follows:
LED_GRN = !!(ivLEDGrnSequence & ivLEDSlot);
LED_GRN = (ivLEDGrnSequence & ivLEDSlot) != 0;
Doing x && 1 produces either 1 or 0, regardless of what non-zero value the left operand evaluates to.
From the C standard:
§6.5.13 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.
It's converting the result of the bitwise AND to either 0 or 1. The result of the bitwise AND can be 0 or any non-zero number. But after the logical AND, the result can only be 0 or 1.
So the first two examples may be useful. The third example with the if statement is definitely not useful, since if converts the expression to a boolean.
The result of logical operation (in this case &&) is either 0 or 1. The result of arithmetic or bitwise operation (& in this case) is 0 or non-0. If we want to convert any non-0 to 1 we perform a logical operation on it. The more common and idiomatic way to accomplish this is the double negation:
LED_GRN = !!(ivLEDGrnSequence & ivLEDSlot);

In C is & shorthand for logical and(&&)?

Sometimes I want to do something like this (with i and j being ints).
(if i==4 && j==9)
{
...
}
Where it'll go through the brackets if i equals 4 and j equals 9. I've been using a single ampersand (&) instead of a double one and my code's been compiling and running.
Is it doing the same thing as a double ampersand &&, and if not what has it been doing?
Edit: Oh and I've been doing the same thing with or, using '|' instead of '||'
Presumably you mean if (i==4 && j==9).
Under the circumstances, changing this from && to & shouldn't change much. The big thing that'll change is that with &&, the j==9 would only be evaluated if the i==4 part was true, but with &, they'll both be evaluated regardless.
When you have something like if (x != NULL && x->whatever ...) you want to ensure that the second part (that dereferences x) is only evaluated if x is not a null pointer. In your case, however, comparing what appear to be ints is unlikely to produce any problems.
It's also possible to run into a problem when you're dealing with something that may produce a value other than 1 to signal true. Again, it's not a problem here because == will always produce either 0 or 1. If (for example) you were using isalpha, islower, etc., from <ctype.h>, they're only required to produce 0 or non-zero values. If you combined those with a &, you'd get a bit-wise or which could produce 0 for two non-zero inputs (e.g., 1 & 2 == 0, but 1 && 2 == 1).
When you use bitwise and on the results from ==, you're going to get 0 & 0 or 0 & 1 or 1 & 0 or 1 & 1. 1 & 1 will yield 1 (true). All the others will yield 0 (false) --- just like && would have.
It's performing a bitwise AND.
What it's doing is the expression i == 4 is equivalent to 1 if i is 4 and the same for the RHS (with j and 9, obviously). The & operator returns the number where both operands have that bit on.
It works the same as && because 00000001 & 00000001 (slimmed down to a byte for example) is the same. If one is 0 (the condition was false), then the & won't see two bits turned on for both operands, and 00000000 is 0, which is falsey.
However, do not simply use & because it's one character shorter or similar. Use it because it expresses what you want to achieve. If it's a logical AND you want, use &&.
The same thing applies to |, except instead of a resulting bit if each operand has it turned on, it turns it on if either operand has that bit turned on.
A single ampersand does a bitwise AND. Every bit of the result is set only if both operands have a 1 in that position.
Since comparisons in C return 1 for true and 0 for false, & will give the same results as && as long as both operands are comparisons. But for arbitrary values, it will return seemingly random results. 1 && 2 is true, but 1 & 2 is false because the binary representations of 1 and 2 have no bits in common.
A single ampersand is called a bitwise and. It is a binary operator that 'ands' two numbers bit by bit.
For instance, if you have two binary numbers, 01100010 and 00011111, your bitwise and will result in 00000010
i==4 returns 1 (true), as does j==9. So, i==4 & j==9 is really just 1 & 1, which evaluates to 1 (true).
Try these examples to see the difference
1) int k = 4 & 6; vs int k = 4 && 6;
2) if(i==4 && 2) vs if(i==4 & 2)

How to toggle an int / _Bool in C

Suppose we have an int and want to toggle it between 0 and 1 in a boolean fashion. I thought of the following possibilities:
int value = 0; // May as well be 1
value = value == 0 ? 1 : 0;
value = (value + 1) % 2;
value = !value; // I was curious if that would do...
The third one seems to work. Why? Who decides that !0 is 1?
Is something wrong with any of these?
Are there other possibilities? e.g. bitwise operators?
Which offers the best performance?
Would all that be identical with _Bool (or bool from stdbool.h)? If not, what are the differences?
EDIT: Many great answers with lots of valuable information, thanks! Unfortunately, I can only accept one.
value = !value; expresses what you want to do directly, and it does exactly what you want to do by definition.
Use that expression.
From C99 6.5.3.3/5 "Unary arithmetic operators":
The result of the logical negation operator ! is 0 if the value of its
operand compares unequal to 0, 1 if the value of its operand compares
equal to 0. The result has type int. The expression !E is equivalent
to (0==E).
The third one seems to work. Why? Who decides that !0 is 1?
C Standard guarantees that !0 is 1.
Are there other possibilities? e.g. bitwise operators?
Yes, you can use the exclusive OR operator:
value ^= 1;
By the way I prefer this to value = !value; as relational and equality operators can result to branching and bitwise operators usually do not.
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
// when you know initial value is either 0 or 1
the language was designed that way.
Use the 3rd one, the others are right but unnecessarly complicated and therefore hiding the intent.
value = (value ^ 1) & 1;
They're all the same after optimisation.
_Bool would have the same results. The only thing different with _Bool is that values are coerced to be either 1 or 0. Meaning that bool x = 55; will have the value x == 1
EDIT: Corrected the formula in 3 because of my brainfart. I let the comments so that people can see my blooper.
value = !value seems the most reasonable one, but you can also use value = 1 - value or value ^= 1. But the last two would both break if value is not 0 or 1. The first one would still work.
There can be noticeable performance issues with the alternatives depending on the architecture:
!a might need in some architectures comparison and branching, which can be expensive depending on the pattern of 'a'
on some architectures there is conditional move (which is branchless), but
which may require still 3 instructions to complete (with dependencies)
1-a most likely needs two instructions in many architectures
counter example: ARM has reverse subtraction RSB %r0, %r0, #1
1^a can be implemented in many architecture with a single instruction
a=(a+1) % 2 will be most likely optimized to a=(a+1)&1, which requires 2 instructions
But anyway the first rule of optimization is that don't optimize a non working code.
To replace !a with a^1, one has to be 100% certain that it produces always the expected value.
Your expression value = value == 0 ? 1 : 0; will work exactly like value = !value;. You can use any of the two.
!0 is always 1 and also !(any non zero value) is 0
Use bitwise NOT operator
var = ~var;

What is !0 in C?

I know that in C, for if statements and comparisons FALSE = 0 and anything else equals true.
Hence,
int j = 40
int k = !j
k == 0 // this is true
My question handles the opposite. What does !0 become? 1?
int l = 0
int m = !l
m == ? // what is m?
Boolean/logical operators in C are required to yield either 0 or 1.
From section 6.5.3.3/5 of the ISO C99 standard:
The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0.
In fact, !!x is a common idiom for forcing a value to be either 0 or 1 (I personally prefer x != 0, though).
Also see Q9.2 from the comp.lang.c FAQ.
§6.5.3.3/5: "The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int."
The other logical operators (e.g., &&, ||) always produce either 0 or 1 as well.
Generally, yes, it'll become 1. That said even if that is guaranteed behavior (which I'm not sure of) I'd consider code that relied on that to be pretty awful.
You can assume that it's a true value. I wouldn't assume anything more.
The Bang operator (!) is the logical not operator found commonly in C, C++ and C#, so
!0 == 1
!1 == 0
This is based on the language characteristic of what is interpreted to be either true or false... in more modern languages it would be like this
!false == true
!true == false
See DeMorgan Law concerning truth tables...
!x will be expand to (x==0) so:
if x=0 -> !x take value from (0==0) = TRUE (value 1)
if x!=0 -> !x take value from (x==0) = FALSE (value 0)

How do I tell if a C integer variable is signed?

As an exercise, I'd like to write a macro which tells me if an integer variable is signed. This is what I have so far and I get the results I expect if I try this on a char variable with gcc -fsigned-char or -funsigned-char.
#define ISVARSIGNED(V) (V = -1, (V < 0) ? 1 : 0)
Is this portable? Is there a way to do this without destroying the value of the variable?
#define ISVARSIGNED(V) ((V)<0 || (-V)<0 || (V-1)<0)
doesn't change the value of V. The third test handles the case where V == 0.
On my compiler (gcc/cygwin) this works for int and long but not for char or short.
#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0)
also does the job in two tests.
If you're using GCC you can use the typeof keyword to not overwrite the value:
#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 })
This creates a temporary variable, _V, that has the same type as V.
As for portability, I don't know. It will work on a two's compliment machine (a.k.a. everything your code will ever run on in all probability), and I believe it will work on one's compliment and sign-and-magnitude machines as well. As a side note, if you use typeof, you may want to cast -1 to typeof (V) to make it safer (i.e. less likely to trigger warnings).
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0))
Without destroying the variable's value. But doesn't work for 0 values.
What about:
#define ISVARSIGNED(V) (((V)-(V)-1) < 0)
This simple solution has no side effects, including the benefit of only referring to v once (which is important in a macro). We use the gcc extension "typeof" to get the type of v, and then cast -1 to this type:
#define IS_SIGNED_TYPE(v) ((typeof(v))-1 <= 0)
It's <= rather than just < to avoid compiler warnings for some cases (when enabled).
A different approach to all the "make it negative" answers:
#define ISVARSIGNED(V) (~(V^V)<0)
That way there's no need to have special cases for different values of V, since ∀ V ∈ ℤ, V^V = 0.
A distinguishing characteristic of signed/unsigned math is that when you right shift a signed number, the most significant bit is copied. When you shift an unsigned number, the new bits are 0.
#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1))
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0
So basically, this macro uses a conditional expression to determine whether the high bit of a number is set. If it's not, the macro sets it by bitwise negating the number. We can't do an arithmetic negation because -0 == 0. We then shift right by 1 bit and test whether sign extension occurred.
This assumes 2's complement arithmetic, but that's usually a safe assumption.
Why on earth do you need it to be a macro? Templates are great for this:
template <typename T>
bool is_signed(T) {
static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>");
return std::numeric_limits<T>::is_signed;
}
Which will work out-of-the-box for all fundamental integral types. It will also fail at compile-time on pointers, which the version using only subtraction and comparison probably won't.
EDIT: Oops, the question requires C. Still, templates are the nice way :P

Resources