Logical operators - c

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.

Related

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.

Does if (!(-1)) evaluate to true or false in 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.

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.

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.

Is the "true" result of >, <, !, &&, || or == defined?

When I for instance write 7>1 in C (say C99 if this is not an always-been feature), can I expect the result will be exactly 1 or just some non-zero value? Does this hold for all bool operators?
In C99 §6.5.8 Relational Operators, item 6 (<,>,<= and >=):
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)
The result has type int.
As for equality operators, it's a bit further in §6.5.9 (== and !=):
The == (equal to) and != (not equal to) operators are analogous to the relational
operators except for their lower precedence) 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.
The logical AND and logical OR are yet a bit further in §6.5.13 (&&)
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
... and §6.5.14 (||)
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
And the semantics of the unary arithmetic operator ! are over at §6.5.3.3/4:
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).
Result type is int across the board, with 0 and 1 as possible values. (Unless I missed some.)
C follows Postel's Law for its boolean operators: be conservative in what you do, be liberal in what you accept from others. It will treat any non-zero value as true in boolean expressions, but it will always produce either a 0 or a 1 itself. 2 != 3 is always 1.
From the ISO C99 standard, section 6.5.8:
6 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. The result has
type int.
From section 6.5.9:
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence. 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.
Same thing happens with the logical conjunction (&&) and disjunction (||) operators.
PS: Incidentally, this is why the bitwise operators (& and |) can usually be used as non-short-circuiting versions of the logical operators.
All C operators that yield logically true/false values always yield a result of type int with the value 0 for false, 1 for true.
That's not the case for all C expressions that yield logically true/false values. For example, the is*() character classification functions declared in <ctype.h> (isdigit(), isupper(), etc.) return 0 if the condition is false, but may return any non-zero value if the condition is true.
As long as you use the result directly as a condition:
if (isdigit(c)) ...
if (!isdigit(c)) ...
if (isdigit(c) || islower(c)) ...
and don't attempt to compare it to something:
if (isdigit(c) == 1) ... /* WRONG */
if (isdigit(c) == true) ... /* ALSO WRONG */
this shouldn't cause any problems.
(You can safely compare the result to 0 or false, but there's no good reason to do so; that's what the ! operator is for.)

Resources