What else can the less than operator mean in C? - c

I am learning bit algorithm and saw the equation that finds the max of two values:
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
The explanation says this equation will find the max without using comparison and "if x < y, then -(x < y) will be all ones". I cannot comprehend what the explanation means because I see a "less than" operator in the equation and if that is an less than operator, (x < y) should return only one bit of data. Therefore, for the explanation to make sense, the sign "<" cannot be the less than operator. I looked at the list of C operators and did not find other meanings for operator "<". Can someone tell me what does the operator "<" do in this equation? Thanks!

This is a very tricky code. The truth is that C does not have any Boolean type: it uses integer instead: 0 for false and 1 for true.
Therefore -(x<y) means
0 if x≥y
-1 if x<y
It is then used as a bit mask.
Edit
As suggested by Jonathan Leffler in comments, C has now a _Bool.
I made this small program to check what is it and how it is used:
#include <stdio.h>
int main() {
_Bool bFalse = 1>2;
printf("size of _Bool: %lu\nsize of comparison result: %lu\n", sizeof(bFalse), sizeof(1>2));
return 0;
}
This outputs:
size of _Bool: 1
size of comparison result: 4
In other words _Bool is one byte (a char), but it is not used as a result of Boolean comparisons (my compiler generates 4 bytes, that is, an int)
Note: tested with Clang on an Intel processor.
Edit: fix the types as kindly suggested in comments (and after checking the clang IR)

"if x < y, then -(x < y) will be all ones"
This is because, if x is less than y, condition evaluates to true (equal to 1). Notice the negetive sign before comparison, it makes the "1" of comparison result as "-1". In binary world, -1 has an all 1 representation, see Two's_complement. Example: 1111 1111 = -1.
However, if x > y, you get a -0 which is again all zero in binary.
Here, '<' is only a "x is_less_than y" comparison check, a logical operator.

Related

C - less than or equal to with bitwise operators

I'm trying to create a function to determine whether x is less than or equal to y.
The legal operators are ! ~ & ^ | + << >>, and the function says "if x <= y then return 1, else return 0"
My thought process is to check whether x-y is negative, and then right shift 31 bits and compare with 1. No matter what adjustments I do, it returns 0, when it's expecting 1.
This is what I have so far:
int isLessOrEqual(int x, int y) {
return (((x - y) >> 31) & 1) | (!(x^y));
}
Can anyone please help me see what I'm doing wrong?
I also tried with all of these return statements:
return (!(x^y)) | (((x+(~y+1)) >> 31 ) & 1);
return ~(((x+(~y+1)) >> 31 ) & 1) | (!(x^y));
return !(((x+(~y+1)) >> 31 ) & 1) | (!(x^y));
return (((x+(~y+1)) >> 31 ) & 1);
return (((x+y+(~1)) >> 31 ) & 1) | (!(x^y));
return (((x+y+(~1) >> 31 ) & 1) | (!(x^y));
return (((x+(~y+1)) >> 31 ) & 0);
I am not going to do your assignment for you, but I will try to get you pointed in the right direction.
My thought process is to check whether x-y is negative, and then right shift 31 bits and compare with 1.
I take you to mean that you want to test whether x-y is negative by shifting the result and comparing with 1, and then to use that in determining the function's return value. That's more or less ok, but there is some room for concern about right shifting negative numbers, as the result is implementation defined. I do not think that's causing you trouble in practice, however.
No matter what adjustments I do, it returns 0, when it's expecting 1.
In some cases, yes. But there are many other cases where that approach, correctly implemented, produces the desired result. About 75% of cases, in fact. Specifically,
it works (only) when x-y does not overflow.
Additionally,
since you're not allowed to use the - operator, you'll need to perform the two's complement conversion and use + instead.
you can avoid the shifting by ANDing with INT_MIN instead of with 1. This yields a nonzero result (INT_MIN) when and only when the other operand of the & has its sign bit set. If you like, you can convert non-zero to exactly 1 by logically negating twice (!!x).
You can slightly simplify the overall computation by using y-x instead of x-y. Then you don't need special accommodation for the x == y case.
You know (or can know) that neither x - y nor y - x overflows when x and y have the same sign.* In that case, you can use one or another variation on testing the arithmetic difference of the arguments. On the other hand, there is a simpler alternative when the two have differing signs (left as an exercise).
To combine those into a single expression, you can compute bitmasks that effect a selection between two alternatives. Schematically:
return (WHEN_SIGNS_MATCH_MASK(x, y) & IS_DIFFERENCE_NON_NEGATIVE(y, x))
| (WHEN_SIGNS_DIFFER_MASK(x, y) & ...);
The WHEN_SIGNS_MATCH_MASK should evaluate to 0 when the signs differ and to -1 (== all bits 1) or another appropriate value when the signs are the same. The WHEN_SIGNS_DIFFER_MASK implements the opposite sense of that sign comparison. The IS_DIFFERENCE_NON_NEGATIVE expands to your subtraction-based computation, and the ... is the alternative approach for the differing-sign case. (I've implied using macros. You don't need to use macros, but doing so will probably make your code clearer.)
*A sufficient condition, but not a necessary one.

C ternary operator, can I omit one part?

I wanted to know if there's a way to omit second or third part of the ternary operator?
I already read this and similar ones but they didn't help.
What I specifically want is something like:
x == y ? x*=2;
however this gives me error as gcc expects another expression also. So are:
x == y ? x *=2 : continue;
x == y ?: x /=2;
What can I do in these situations except:
if(x == y) do_something;
Edit for further clarification:
As my question seems to be confusing and got all kinds of comments/answers my point was when thinking logically, an else is required after if , so is the default statement in a switch however, neither are mandatory. I was asking if it's the case with ?: also and if so, how.
I wanted to know if there's a way to omit second or third part of the ternary operator?
No, not in standard C.
You can substitute expressions or statements that do not use the conditional operator at all, but in standard C, the conditional operator requires three operands, just like the division operator (/) requires two. You cannot omit any.
Nor is it clear why you want to do. The primary thing that distinguishes the conditional operator from an if [/ else] statement is that expressions using the conditional operator are evaluated to produce values. If you're not interested in that value then using a conditional expression instead of a conditional statement is poor style. A standard if statement is much clearer, and clarity is king. This is a consideration even when you do want the value.
What can I do in these situations except:
if(x == y) do_something;
You can go have a coffee and hope the mood passes.
But if it doesn't, then the logical operators && and || have short-circuiting behavior that might suit, as #EricPostpischil already observed:
a && b is an expression analogous to if (a) b;. It evaluates a, after which there is a sequence point. If a was truthy then it evaluates b and that is the result of the expression; otherwise it does not evaluate b and the value of a is the value of the expression. That is the C version of the hypothetical a ? b : (nothing), and why C does not need the latter.
Similarly, a || b is an expression analogous to if (!a) b;. b is evaluated and yields the result of the expression if and only if a is falsey. That is the C version of the hypothetical a ? (nothing) : b.
But here again, it is poor C style to use && and || expressions exclusively for their side effects. If you don't care about the result of the operation, then use an if statement.
Or perhaps poor style is the point? If you're shooting for an entry in the International Obfuscated C Code Contest then abusing operators is par for the course. In that case, you could consider rewriting your expressions to use the ternary operator after all. For example,
x == y ? x *=2 : continue;
could be written as x *= ((x == y) ? 2 : 1), provided that you weren't actually trying to get loop-cycling behavior out of that continue. And
x == y ?: x /=2;
could be rewritten similarly. Though if you were actually looking toward IOCCC, then there are better obfuscation options available.
For the purpose asked about in this question, in which the result value of the conditional operator would not be used:
For a ? b : c without b you can use a && b, which will evaluate b if and only if a is true.
For a ? b : c without c you can use a || c, which will evaluate c if and only if a is false.
These expressions will have different values than a ? b : c, but that does not matter when the value is not used.
Without some exceptional circumstance to justify this, most experienced programmers would consider it bad practice.
GCC has an extension that uses the first operand for a missing second operand without evaluating it a second time. E.g. f(x) ? : y is equivalent to f(x) ? f(x) : y except that f is only called once.
Similar to the 'hyphen-ish' character of "-1" being called "unary minus", "?:" is called "trenary" because it requires 3 parts: the condition, the "true" case statement and the "false" case statement. To use "?:" you must supply 3 "terms".
Answering the question in the title, no, you cannot omit one part.
The following responds to "What can I do in these situations except:"
Given that your two examples show an interest in performing (or not) a mathematical operation on the variable 'x', here is a "branchless" approach toward that (limited) objective. ("Branchless" coding techniques seek to reduce the impact of "branch prediction misses", an efficiency consideration to reduce processing time.)
Note: the for() loop is only a "test harness" that presents 3 different values for 'y' to be compared to the value of 'x'. The variable 'n' makes more obvious your OP constant '2'. Further, as you are aware, performing multiplication OR division are two completely different operations. This example shows multiplication only. (Replace the '*' with '/' for division with the standard caveat regarding "division by zero" being undefined.) Depending on the probability of "cache misses" and "branch prediction" in modern CPUs, this seemingly complex calculation may require much less processing time than a 'true/false branch' that may bypass processing.
int n = 2; // multiplier
for( int y = 4; y <= 6; y++ ) { // three values for 'y'
int xr = 5; // one value for 'xr'egular
int xb = 5; // same value for 'xb'ranch
(xr == y) ? xr *= n : 1; // to be legitimate C
// when x == y the rhs becomes (n-1)*(1)+1 which equals n
// when x != y the rhs becomes (n-1)*(0)+1 which equals 1 (identity)
// Notice the rhs includes a conditional
// and that the entire statement WILL be evaluated, never bypassed.
xb *= ((n-1)*(xb==y))+1;
printf( "trenaryX = %2d, branchlessX = %2d\n", xr, xb );
}
Output
trenaryX = 5, branchlessX = 5
trenaryX = 10, branchlessX = 10
trenaryX = 5, branchlessX = 5
I hope this makes clear that "trenary" means "3 part" and that this digression into "branchless coding" may have broadened your horizons.
You can use the fact that the result of comparison operators is an int with value 0 or 1...
x == y ? x*=2;
x *= (x == y) + 1; // multiply by either 1 or 2
But a plain if is way more readable
if (x == y) x *= 2;
x == y ? x*=2 : 1;
The syntax requires all three parts... But, if you write code like this, you will lose popularity at the office...
Repeating for those who might have missed it: The syntax requires all three parts.
Actually, you shouldn't do this because as #user229044 commented, "if (x==y) do_something; is exactly what you should do here, not abuse the ternary operator to produce surprising, difficult-to-read code that can only cause problems down the line. You say "I need to know if that's possible", but why? This is exactly what if is for."
As in ternary operator without else in C, you can just have the third/second part of the ternary operator set x to itself, for example, you can just do:
x = (x == y ? x *= 2 : x);
or
x == (y ? x : x /= 2);

Integer overflow test operator? (&+)

This question could just be another case of interpreting the operator incorrectly. But a while ago, I saw someone tweeting about an operator that allegedly can be used to check for integer overflow in C. Namely the &+ (ampersand-plus) operator, and it could be used simply like so:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint32_t x, y;
x = 0xFFFFFFFF;
y = 1;
if (x &+ y) {
printf("Integer overflow!\n");
} else {
printf("No overflow\n");
}
return 0;
}
It does seem to work as one would expect, and GCC 6 doesn't throw me any warnings or errors when compiling it with these parameters: gcc -Wall -Wextra -Werror of.c
But oddly enough, I have yet to find any documentation about this operator, and I never saw it used anywhere. Could someone please explain how this works?
The expression
x &+ y
is parsed as
x & (+y)
using the unary plus operator, which has no effect (in this case) and just returns y. That means the expression is equivalent to
x & y
which does not test for integer overflow and instead just checks if x and y have any bits in common. Try changing x and y to 1 and see what happens; it'll report an overflow even though none will occur.
That was probably a joke, there's no such a thing as the &+ operator. If you write x&+y, it is interpreted as x & (+y), where & is the binary bitwise and operator, and + is the unary plus operator which does nothing besides possibly performing arithmetic promotion (e.g. if y is a short or char it gets promoted to an int; in your case it does nothing).
Anyhow, this expression doesn't really have a strict relation with checking for overflow.
Your probably want to use __builtin_add_overflow (fully generic, and somewhat less common) or __builtin_uadd_overflow (for unsigned ints)
#include <stdio.h>
#include <stdint.h>
int main()
{
uint32_t x, y;
x = 0xFFFFFFFF;
y = 1;
if (__builtin_add_overflow(x, y, &x)) {
printf("Integer overflow!\n");
} else {
printf("No overflow\n");
}
return 0;
}
There are no builtin-checking operators in gcc/clang, AFAIK, and &+ is just & followed by a unary +.
I'm personally using a wrapper macro that uses these builtins, if they're available, or falls back to a builtin-less solution inspired by the overflow checking code that's available at
https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow

Replacing “!=” with bitwise operators

using only bitwise operators (|, &, ~, ^, >>, <<), is it possible to replace the != below?
// ...
if(a != b){
// Some code
}
/// ...
this is mainly out of self interest, since I saw how to do it with == but not !=.
if(a ^ b) {
//some code
}
should work.
You can also use your preferred method for == and add ^ 0xFFFFFFFF behind it (with the right amount of Fs to match the length of the datatype). This negates the value (same as ! in front of it).
a != b means that there is at least one different bit in the bit representations of a and b. The XOR bit operator returns 1 if both input bit operands are different, 0 otherwise.
So, you can apply a XOR operation to a and b and check if the result is not equal to zero.
A bitwise version of the '!=' test could look something like:
if((a - b) | (b - a)) {
/* code... */
}
which ORs the two subtractions. If the two numbers are the same, the result will be 0. However, if they differ (aka, the '!=' operator) then the result will be 1.
Note: The above snippet will only work with integers (and those integers should probably be unsigned).
If you want to simulate the '==' operator, however, check out Fabian Giesen's answer in Replacing "==" with bitwise operators
x ^ y isn't always sufficient. Use !!(x ^ y). Values expecting a one bit return value will not work with x ^ y since it leaves a remainder that could be greater than just 1.
Yes, using this:
if (a ^ b) { }
"~" is equaled to NOT so that should work. example would be "a & ~b".

Replacing "==" with bitwise operators

Using only bitwise operators (|, &, ~, ^, >>, <<) and other basic operators like +, -, and !, is it possible to replace the "==" below?
int equal(int x, int y) {
return x == y;
}
Remember that an XOR is the exactly same as NOT EQUALS and XNOR is exactly the same as EQUALS. So, the following will give you exactly what you want:
return !(x ^ y);
Two numbers are equal if there is no difference between them:
int equal(int x, int y){
return !(x-y);
}
The C ! operator is really just shorthand for != 0, so using it seems very close to cheating :)
Here's my take just using bitwise operations, assuming a 32-bit two's complement machine with arithmetic right shifts (technically, in C arithmetic right shifts are undefined, but every C compiler I've ever seen on a two's complement machine supports this correctly):
int t = (x - y) | (y - x); // <0 iff x != y, 0 otherwise
t >>= 31; // -1 iff x != y, 0 otherwise
return 1 + t; // 0 iff x != y, 1 otherwise
That said, actual compilers don't have this problem. Real hardware actually has direct support for comparisons. The details depend on the architecture, but there's two basic models:
Condition codes returned for arithmetic operations (e.g. x86 and ARM do this). In this case, there's usually a "compare" instruction which subtracts two values, doesn't write back to an integer register but sets the condition code/flags based on the result.
More RISC-like platforms typically have direct "branch if equal" and "branch if less than" operands that do a comparison and branch based on the result. It's basically equivalent to the C code
if (a == b) goto label;
or
if (a < b) goto label;
all in one machine instruction.
This example is the same as subtraction, but is more explicit as to how some architectures do register comparison (like the ARM, I believe).
return !(1 + ~x + y);
The 1 signifies the carry-bit input into the ALU. One number x is bitwise complemented. Taking the complement and adding 1 produces the two's complement of the number (x becomes -x), and then it's added to the other number to get the difference to determine equality.
So if both numbers are equal, you get -x + x => 0.
(On a register level the ! operator isn't done, and you just test the "zero bit" of the condition codes or flags register, which gets set if the register operation produces a result of zero, and is clear otherwise.)
As XOR is same as (!=), hence (x ^ y) will return 0 only for equal values.
My take is the following because it is sensible, uses bit-wise operator and working.
int notEqual(int x, int y){
return (x ^ y);
}
My Take on this
int equal(int x, int y){
if((x & ~y) == 0)
return 1;
else
return 0;
}
Explanation: If x == y, then x & ~y evaluates to 0 return 1, else return 0 as x!=y.
Edit1: The above is equivalent to
int equal(int x, int y){
return !(x & ~y) ; // returns 1 if equal , 0 otherwise.
}
The above code fails in certain cases where the Most significant bit turns to 1. The solution is to add a 1. i.e correct answer is
return !(x & (~y +1) );

Resources