let x = (0&0xFFFFFFFF) + ~0 +1 , what is the value of x? - c

I'm working on a c bit homework, for one of the questions it is asking me to implement logical negation without using '!'; this is what I came up with:
`
(0 & 0xFFFFFFFF) // S1: 0s & ones should return 0s right?
+ ~0 +1 // S2: then to the value above I add 1 and the not value of 0 (which in my understanding is 0xFFFFFFFF)
`
Now in human language, S1 result: 0x0000 , S2: 0x0000 - 0 + 1
which should end up returning 1. I instead get 0. Where am I going wrong here??
Thanks in advance :)
edit:
do you think there's hope for this approach if modified? and counting the fact that I can pass a non zero number that should give me a 0 as a result. !(n) = 0 unless n ==0 then it should return 1.

(0 & 0xFFFFFFFF) certainly forms an unsigned 0 or unsigned long 0 as 0xFFFFFFFF is a hexadecimal constant that first fits into one of those 2 types. #Eric
0 is a signed 0. ~0 flips all the bits - the result remains signed. With the very common 2's complement encoding, this is a signed -1.
Then the addition of an unsigned 0 with ~0 becomes unsigned 0xFFFFFFFF or 0xFFFF as -1 is first converted to an unsigned, etc. depending on the bit width of int/unsigned.
Adding 1 to that, the value is 0. The result is unsigned.
Where am I going wrong here?
Adding ~0 is not like subtracting 0.
implement logical negation without using '!';
This requires shifts or ifs and often implementation depended code or simply:
y = x == 0;
Soapbox: IMO, it is a poor assignment for a learner as it encourages implementation dependent code. C has !` for a reason.

Now in human language, S1 result: 0x0000 , S2: 0x0000 - 0 + 1
~0 is not -0, it's -1. If necessary, read up on two's complement encoding.
So your expression is:
(0 & 0xFFFFFFFF) + ~0 +1 =
(0 & whatever) + ~0 + 1 =
0 + ~0 + 1 =
~0 + 1 =
-1 + 1 =
0

This expression in which each operand has the type int
~0 +1
is equivalent to (if to use the internal representation)
0xFFFFFFFF + 1
that in turn is equal to
-1 + 1
provided that the compiler uses the 2's complement representation of integers that yields 0.
So S1 and S2 are both equal to 0 and hence the result is also equal to 0.

Related

Value of x when s = x >> 31 and x = (s & ~x) | (~s & x);

If x was to equal 12 in a 32 bit scenario, x = multiple 0's into the lsb 0000 1100. If the above scenario were to run, I believe I would get 0000 1100. Am I wrong?
Along with that, what if I was to use x=-1? Wouldn't s = 1, but then does (s & ~x) look like (0001 & 0000) and (1110 & 1111)? Thanks
I thought that x=-1 would mean x>>31 would be like 0001 (output 1), but I don't know if the above is correct.
The typical implementation of a right shift of a signed integer is an arithmetic shift. Different implementations are unfortunately still allowed, though rare, and they're not relevant to understanding this code (it ignores such possibilities anyway). Two's complement integers are now mandatory (in C23: "The sign representation defined in this document is called two’s complement. Previous revisions of this document
additionally allowed other sign representation") so I'm not going to do the usual consideration of hypothetical integer representations that haven't been seen since the stone age.
By assumption the number of bits in an int is 32, so shifting an int right by 31 makes every bit of the result a copy of the sign bit. So if x was negative, s would be -1.
x = (s & ~x) | (~s & x) is a verbose way to spell out x ^= s. XORing x by 0 leaves it the same as before, XORing it by -1 inverts all the bits. Taking into account that s = x < 0 ? -1 : 0, effectively the computation does this:
if (x < 0)
x = ~x; // equivalent to: x = -x - 1;

Bit manipulation for identity property

Given an integer and either 1 or 0, I'd like to be able to get either the integer or 0 using only bitwise operators. That means no if statements, conditionals, etc. Basically integer * i. Two's complement system!
I have been working for a while and it is tricky. Here are my failed attempts:
Edit: ints are unsigned
unsigned int x = 24; // To change
unsigned int i = 0; // identity
((~i) | x) // if i = 0, ~i returns 111...1 || (111...1 | x) = 111...1
// else ~i returns 000...1 || (000...1 | x) = x (+1 sometimes)
The code I have above makes it so if i is 1, then I get the identity (only sometimes), and if i is 0, then I get -1. I'd like it so if i is 1, I get the identity, and if i is 0, I get 0. Thanks!
I think this is what you want:
i & -x
If x is zero, you get i & 0 which is zero. If x is one, you get i & UINT_MAX which is i.
This can be done using
~i + 1u & x
~0u produces UINT_MAX (all bits 1):
1111...1111
Adding 1 goes back to 0:
0000...0000
On the other hand, ~1u produces UINT_MAX - 1:
1111...1110
Adding 1 then gives UINT_MAX (all bits 1):
1111...1111
These are perfect bit masks to use with &: (0 & x) == 0 and (UINT_MAX & x) == x.

Formula to convert byte array representing signed integer into integer

This question is more generic without a particular language. I am more interested in solving this generally across languages. Every answer I find references a built-in method of something like getInt32 to extract an integer from a byte array.
I have a byte array which contains the big-endian representation of a signed integer.
1 -> [0, 0, 0, 1]
-1 -> [255, 255, 255, 255]
-65535 -> [255, 255, 0, 1]
Getting the values for the positive cases are easy:
arr[3] | arr[2] << 8 | arr[1] << 16 | arr[0] << 24
What I would like to figure out is the more general case. I have been reading about 2s complement, which lead me to the python function from Wikipedia:
def twos_complement(input_value, num_bits):
'''Calculates a two's complement integer from the given input value's bits'''
mask = 2**(num_bits - 1) - 1
return -(input_value & mask) + (input_value & ~mask)
which in turn lead me to produce this function:
# Note that the mask from the wiki function has an additional - 1
mask = 2**(32 - 1)
def arr_to_int(arr):
uint_val = arr[3] | arr[2] << 8 | arr[1] << 16 | arr[0] << 24
if (determine_if_negative(uint_val)):
return -(uint_val & mask) + (uint_val & ~mask)
else:
return uint_val
In order for my function to work I need to fill in determine_if_negative (I should mask the signed bit and check if it is 1). But is there a standard formula to handle this? One thing I found is that in some languages, like Go, the bitshift might overflow the int value.
This is pretty hard to search because I get a thousand results explaining the difference between big-endian and little-endian or results explaining twos complement, and many more giving examples of using the standard library but I haven't seen a complete formula for bitwise functions.
Is there a canonical example in C or similar language of converting a char array using only array access and bitwise functions (ie, no memcpy or pointer casting or tricky stuff)
The bitwise method only works properly for unsigned values so you will need to build the unsigned integer and then convert to signed. The code could be:
int32_t val( uint8_t *s )
{
uint32_t x = ((uint32_t)s[0] << 24) + ((uint32_t)s[1] << 16) + ((uint32_t)s[2] << 8) + s[3];
return x;
}
Note, this assumes you are on a 2's complement system which also defines unsigned->signed conversion as no change in repesentation. If you want to support other systems too , it would be more complicated.
The casts are necessary so that the shift is performed over the right width.
Even c might be too high level for this. After all, the exact representation of int is machine dependent. On top of that, not all integer types on all systems are 2s complement.
When you mention a byte array and converting it to integer you must specify what format that byte array implies.
If you assume 2s complement and little endian (like intel/amd). Then the last byte contains the sign.
For simplicity's sake lets start with a 4 digit 2s complement integer,then byte byte, then 2 byte integers and then 4.
BIN SIGNED_DEC UNSIGNED_DEC
000 0 0
001 1 1
010 2 2
100 -4(oops) 4
101 -3 5
110 -1 6
111 -1 7
---
123
let each bit be b3,b2,b1, where b1 is the most significant bit(and sign)
then the formula would be:
b3*2^2+b2*2^1-b1*4
for a byte we have 4 bits and the formula would look like this:
b4*2^3 + b3*2^2+b2*2^1-b1*2^3
for 2 bytes it is the same but we have to multiple the most significant byte by 256 and the negative value would be 256^2 or 2^16.
/**
* returns calculated value of 2s complement bit string.
* expects string of bits 0or1. if a chanracter is not 1 it is considered 0.
*
*/
public static long twosComplementFromBitArray(String input) {
if(input.length()<2) throw new RuntimeException("intput too short ");
int sign=input.charAt(0)=='1'?1:0;
long unsignedComplementSum=1;
long unsignedSum=0;
for(int i=1;i<input.length();++i) {
char c=input.charAt(i);
int val=(c=='1')?1:0;
unsignedSum=unsignedSum*2+val;
unsignedComplementSum*=2;
}
return unsignedSum-sign*unsignedComplementSum;
}
public static void main(String[] args) {
System.out.println(twosComplementFromBitArray("000"));
System.out.println(twosComplementFromBitArray("001"));
System.out.println(twosComplementFromBitArray("010"));
System.out.println(twosComplementFromBitArray("011"));
System.out.println(twosComplementFromBitArray("100"));
System.out.println(twosComplementFromBitArray("101"));
System.out.println(twosComplementFromBitArray("110"));
System.out.println(twosComplementFromBitArray("111"));
}
outputs:
0
1
2
3
-4
-3
-2
-1

Constant time string equality test return value

Looking for a constant time string equality test I found that most of them use bit trickery on the return value. For example this piece of code:
int ctiszero(const void* x, size_t n)
{
volatile unsigned char r = 0;
for (size_t i = 0; i < n; i += 1) {
r |= ((unsigned char*)x)[i];
}
return 1 & ((r - 1) >> 8);
}
What is the purpose of return 1 & ((r - 1) >> 8);? Why not a simple return !r;?
As mentioned in one of my comments, this functions checks if an array of arbitrary bytes is zero or not. If all bytes are zero then 1 will be returned, otherwise 0 will be returned.
If there is at least one non-zero byte, then r will be non-zero as well. Subtract 1 and you get a value that is zero or positive (since r is unsigned). Shift all bits off of r and the result is zero, which is then masked with 1 resulting in zero, which is returned.
If all the bytes are zero, then the value of r will be zero as well. But here comes the "magic": In the expression r - 1 the value of r undergoes what is called usual arithmetic conversion, which leads to the value of r to become promoted to an int. The value is still zero, but now it's a signed integer. Subtract 1 and you will have -1, which with the usual two's complement notation is equal to 0xffffffff. Shift it so it becomes 0x00ffffff and mask with 1 results in 1. Which is returned.
With constant time code, typically code that may branch (and incur run-time time differences), like return !r; is avoided.
Note that a well optimized compiler may emit the exact same code for return 1 & ((r - 1) >> 8); as return !r;. This exercise is therefore, at best, code to coax the compiler input emitting constant time code.
What about uncommon platforms?
return 1 & ((r - 1) >> 8); is well explained by #Some programmer dude good answer when int is 8-bit 2's complement - something that is very common.
With 8-bit unsigned char, and r > 0, r-1 is non-negative and 1 & ((r - 1) >> 8) returns 0 even if int is 2's complement, 1's complement or sign-magnitude, 16-bit, 32-bit etc.
When r == 0, r-1 is -1. It is implementation define behavior what 1 & ((r - 1) >> 8) returns. It returns 1 with int as 2's complement or 1's complement, but 0 with sign-magnitude.
// fails with sign-magnitude (rare)
// fails when byte width > 8 (uncommon)
return 1 & ((r - 1) >> 8);
Small changes can fix to work as desired in more cases1. Also see #Eric Postpischil
By insuring r - 1 is done using unsigned math, int encoding is irrelevant.
// v--- add u v--- shift by byte width
return 1 & ((r - 1u) >> CHAR_BIT);
1 Somewhat rare: When unsigned char size is the same as unsigned, OP's code and this fix fail. If wider math integer was available, code could use that: e.g.: return 1 & ((r - 1LLU) >> CHAR_BIT);
That's shorthand for r > 128 or zero. Which is to say, it's a non-ASCII character. If r's high bit is set subtracting 1 from it will leave the high bit set unless the high bit is the only bit set. Thus greater than 128 (0x80) and if r is zero, underflow will set the high bit.
The result of the for loop then is that if any bytes have the high bit set, or if all of the bytes are zero, 1 will be returned. But if all the non-zero bytes do not have the high bit set 0 will be returned.
Oddly, for a string of all 0x80 and 0x00 bytes 0 will still be returned. Not sure if that's a "feature" or not!

Output a = ~a + 2 << 1 ;

Please help out with understanding of the output of the following c program statement.
a = ~a + 2 << 1 ;
printf("Value of A is %d",a);
Value of A comes out to be -2.
I am assuming that a is an signed int and initialized as 2. I am also assuming this is two's complement. (I have also omitted the bytes above the first byte as they don't have a meaning on the result of this answer).
The ~ (tilde) is the bitwise not operator. That is it will make any 1 into 0 and any 0 into 1. The << is a bit shift to the left operation.
So in the start we got 00000010 as the bits in a. As we do the not operator we get 11111101 which would give us the number -3.
We then add 2 to that so we get 11111111 or -1. We then bitshift this one to the left and we have 11111110 which equals -2.

Resources