Does if (!(-1)) evaluate to true or false in C? - c

I know that 0 and NULL evaluate to FALSE on their own and I know that a negative integer or a positive integer evaluate to TRUE on their own.
My understanding is that the NOT operation will happen after evaluating the expression, so if (-1) will evaluate to TRUE, then applying the ! operand will mean NOT TRUE which equals FALSE. Is this the correct order of operations and is it correct that if (!(-1)) will evaluate to FALSE?

The evaluation of if (!(-1)) can be worked out by thinking about the operator precedences.
Firstly the unary - is applied to 1 which produces an integral -1. Then this value is logically negated by the !. This involves collapsing -1 into a logical value. The rule for this in C is nice and simple for integral types: 0 is falsy and everything else is truthy.
Therefore -1 is truthy and when the logical negation happens we get false.
Therefore this statement is portably false.

In standard C, any non-zero (positive/negative) value is TRUE.
So, (-1) evaluated as TRUE and, !(-1) of-course evaluated as FALSE. Hence, if (!(-1)) will evaluate to FALSE.

(-1) = 1111 1111 in binary and ! flips all bits so the byte would equal 0000 0000 which is equal to false.

Related

Why does the logical statement !0x00 return 0x01 in C?

I'm reading Computer Systems a programmers perspective, and I'm getting into logical operators, which are similar to bitwise operators, but with a few differences.
What I CANNOT figure out is that when you have a logical operand !0x00 returns 0x01 rather than 0x11?
! is NOT, right? So NOT 0(false) should be 1(true) and another NOT 0(false) should also be 1(true) as well, right?
I look at the bitwise operator example : ~00, naturally that would return 11, but C's logical operators seem to work with vast differences.
Why does this happen?
What I have tried already: Reading a little further to find the answer I seek, it doesn't seem to be here.
What I think the problem is: Might have something to do with how Hexadecimals work? But, Hexadecimals can still have 0x11. . . .
Because that's how the language is defined. ! is the logical NOT operator and boolean logic in C works on 1 and 0, representing true and false.
C17 6.5.3.3:
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.
You can think of it as if returning bool, though it actually returns int for backwards-compatibility reasons. Unlike C++ where it does return bool. The same goes for relational and equality operators.
The expression !n is equivalent to (n==0). It returns 1 if true, 0 if false.
Neither !0x00 nor ~0x00 will give you 0x11.
!n is the same as n==0 and evaluates to 1 or 0.
~n negates the bits of the binary representation, not the digits of the literal you chose to enter the number.

C by K&R - numeric value of a relational or logical expression

In section 2.6 "Relational and Logical Operators" on page 42 in "The C Programming Language" 2nd by K&R, the authors said:
By definition, the numeric value of a relational or logical expression
is 1 if the relation is true, and 0 if the relation is false.
I'm confused by that wording. For example, in the logical expression
x && y
there is no relation which can be true or false. Isn't the wording supposed to be:
By definition, the numeric value of a relational or logical expression
is 1 if the expression is true, and 0 if the expression is false.
x && y
Since x and y are being used in conjuntion with && the compiler needs logical (boolean)values
In c 0 is false and not 0 is true. Hence the statement you posted from the standard that a logical expression evaluates to 0 or not zero (in fact 1, but in testing any non zero value is treated as true).
Thus this code is interpreted as
(x != 0) && (y != 0)
the depending of the current values of x and y this becomes, say
1 && 0
THis is
true && false
by the rule that 0 == false and !0 == true. This expression is thus false, and therefore evaluates to 0 by the statment you posted.
Note that much of this confusion comes form the fact the c originally had no boolean type. Hence the convention that 0 = false and !0 = true. This has the beneficial side effect of allowing numbers and in particular pointers to be tested directly as in
while(ptr--)
{
}
Which is equivalent to
while(ptr-- != 0)
{
}
A relational or logical expression is the result of an operator such as &&, ||, ==, '>=,<=, etc. In this context,x && y` is a logical expression which will evaluate to either 0 or 1.
The arguments to && need not be logical expressions. When evaluated in a boolean context, a numeric value of 0 evaluates to false while a non-zero value evaluates to true. So in the case of x && y the expression will evaluate to 1 (i.e. true) if both x and y are non-zero.
This is not relational operator.(You shouldn't take the word relation on that context also). This is logical AND. The wording is correct.
Here each of the variable's value x and y if non zero will evaluate to truthy value. And if both of them are true then it will be true - the whole expression would be true.
And here by relation it means the relation of each subexpression being truthy or not which in turn decides whether whole expression is true or false. In your case the relation is simply whether x is nonzero or not AND y is nonzero or not.
The wording is correct. Relation is a mathematical term.
Every operator in C returning a boolean can be considered a relation.

Expressions in c return 1 for true

In c programming ,all non zero numbers can be used in conditional expressions to return true. In that aspect why do expressions which evaluate to true return 1 ,not any other non zero value?
#include<stdio.h>
int main()
{
printf("%d",6==6);
}
output: 1
This is defined in 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.
Similar for the other logical operators.
It makes a lot of sense to have a deterministic value for these cases, and the lowest positive non-zero value is a good candidate for that.
C11 draft
6.5.9 Equality operators
3
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.
Because as you said, evaluating the both sides of that kind of expressions, the result could be true or false, that is a boolean value. By definition and convetion, in C standard, boolean values are represented with a 1 for true and 0 for false.

Logical operators

I have come across an answer and I can't seem to figure out why it's right.
So there are two int variables x and y and they represent 0x66 and 0x39 respectively.
The question asked what is the result value based on the expression.
x && y is apparently 0x01 (1)
x || y is 1
!x || !y is 0
x && ~y is 1
From what I was thinking, I thought as long as an argument was not zero it was considered true. So as long as x and y were some non-zero value then && operator would produce a 1, and of course as long as one of them is true the || operator would produce a 1.
So why is the third question 0? Is the ! different from the bitwise ~ operator? So originally x is 0101 0101 in binary since it's non zero it is true in the logical sense, but the ! of it would be false or would it do the one's complement of the number so its 1010 1010?
A boolean result is always true or false, and in C true is represented by 1 and false by 0.
The logical not operator ! gives a boolean result, i.e. 1 or 0. So if an expression is "true" (i.e. non-zero) then applying ! on that expression will make it false, i.e. 0.
In your example you have !x || !y. First !x is evaluated, and it evaluates to false, leading to !y being evaluated, and it also evaluates to false, so the while expression becomes false, i.e. 0.
From what I was thinking, I thought as long as an argument was not
zero it was considered true. So as long as x and y were some non-zero
value then && operator would produce a 1, and of course as long as one
of them is true the || operator would produce a 1.
This is all correct.
So why is the third question 0? Is the ! different from the bitwise ~ operator?
Yes. It is logical NOT. Just like the other logical operators && and ||, it only cares about if a variable has a non-zero value or not.
!0 will yield 1.
!non_zero will yield 0.
Note that all logical operators in C yield type int rather than bool, as an ugly, backwards-compatibility remain from the time before C had a boolean type. In C++ and other C-like languages, logical operators always yield type bool.
Similarly, true and false in C are actually just macros that expand to the integers 1 and 0. In other languages they are keywords and boolean constants.
Yes, ! is different from the bitwise not ~. It's a logical not. It yields either 0 or 1.
~(0x01) will 0x10 and
!(0x01) will 0x00
'~' is a bitwise operator.
'!' is a logical operator.

What is the difference between ~~x and !!x in C?

I am trying to check if any bit of an int x equals to 1, and the answer is !!x. I googled a bit and didn't find anything about why this is correct.
So say if I have a number x is 1010.
What would !x be? What is the different between !x and ~x?
! is a logical operator which takes the value of the operand of scalar type.
To quote C11, chapter ยง6.5.3.3, 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. [...]
OTOH, ~ is a bitwise operator which performs bitwise negation of the operand of integer type.
Related,
The result of the ~ operator is the bitwise complement of its (promoted) operand (that is,
each bit in the result is set if and only if the corresponding bit in the converted operand is
not set). The integer promotions are performed on the operand, and the result has the
promoted type. [...]
For example, consider binary number 10.
!10 is 0.
~10 is 01.
EDIT:
FWIW, is you use !!, the result you can get is either 0 or 1. OTOH, is you use ~~, you get back the original value of the operand.
The range of possible values of !x are 0 and 1.
~ (the bitwise complement) has the same range as its domain.
So ~~x will recover x, but !!x will not necessarily do that.
I am trying to check if any bit of an int x equals to 1, and the answer is !!x [...]
No, "the answer" (i.e. the proper way to write this check in C) is simply x != 0. That's much clearer, and doesn't make the reader think. Using two logical inversions computes the same value, but is much less clear.
Quoting the draft C11 spec, we have:
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).
So, there really isn't any difference.
Also, regarding negative zero, the standard requires that
For any integer type, the object representation where all the bits are zero shall be a representation of the value zero in that type.
So, checking for "all bits zero" for an integer really is the same as comparing to (non-equality to) 0.
! : is a logical operator, which when operated gives only true or false as result. It converts true to false and false to true.
~ : is a bit-wise negation operator i.e. if a particular bit of some value is 0, it flips that bit to 1 and vice versa. Please note, it doesn't operate on the value as a whole, it only operates only on a bit.
In C, only numeric value 0 (i.e. 1-byte binary equivalent: 00000000) is logically false, everything else is true. Any value with even one of the bit equal to 1 in its binary equivalent is true. So,
/*Use and explanation of !x*/
int x = 1; //binary equivalent: 00000001 is logically true. it can be checked as follows
if (x) // if statement coerces x to boolean equivalent which is true.
printf("%d is true", x);
The printf statement in above code snippet will be executed.
Now, when not logical operator is used on x (i.e. !x) the result is false as x ( =1 ) is logically true. Using it two times (i.e. !!x) will make it true again.
NOTE: using it first time caused two things
Caused type conversion of value 1 to boolean equivalent(i.e. true).
Changed the boolean (from step 1) to its opposite (i.e. false).
So, basically not logical operator can be used to check if something is true or false. Using it twice returns actual boolean equivalent of the value being checked.
/*Use case of ~x (bit-wise negation operator)*/
int x = 1; //binary equivalent: 00000001
int y = ~x; //Now, y will be ~x i.e. 11111110. it can be checked as follows.
printf("%d: value after operation of bit-wise operator", y);
//The printf statement will print decimal equivalent of 11111110 i.e. -2.
y = ~y; // i.e. y = ~~x, this will again flip the bits and make y equal to 1 i.e. 00000001.
printf("%d: value after double operation of bit-wise operator", y);
So, when it is required to check whether any of the bit in some value is 1 or not, basically it implies to check whether that value is logically true or not. And that can be checked using if statement (as shown above) or using even number of logical not operators, as shown below
int x = 1;
if(!!x)
printf("x is true");
The NOT logical operation in C is represented by the operator !.
In C every null value means FALSE (like 0, 0.0 or the null pointer constant NULL). OTOH, every non-null is considered as meaning TRUE.
The logical negation makes an inversion of the logical value, thus converting every non-zero value in the integer value 0, and every zero value is converted in the integer value 1.
Then, a double negation only can be 0 or 1.
Now, if an object represents an arithmetical value, all its bits are 0 if and only if the value is 0 or 0.0. So the negation of such an object is equal to !0, that is, 1. Besides, if an object like 10101010, whose bits are not all 0, is just a non-null value, so its negation is 0 (that is !10101010 == 0).
Finally, you have !!0 == 0 and !!(non-zero-value) == 1.
The bitwise negation in C is represented by the operator ~.
In this case, the action of negation is done on each separated bit.
For example: ~11100111 == 00011000.
So, if you apply the bitwise negation operator twice, the original value is recovered: ~~x == x.

Resources