The right order of shifting bits in c - c

What is the difference and why are there 3(???) different results?
signed char b;
b = 66 << 2 >> 8;
fprintf(stdout, "%d\n", b);
Output: "1"
signed char b;
b = 66 << 2;
b = b >> 8;
fprintf(stdout, "%d\n", b);
Output: "0"
signed char b;
b = 2 >> 8;
b = 66 << b;
fprintf(stdout, "%d\n", b);
Output: "66"
thanks for help!

signed char b = 66 << 2 >> 8;
Here, 66 << 2 becomes a signed int 264 (signed int because it is an intermediate result), which is shifted >> 8, which becomes 1.
signed char b = 66 << 2;
Here, the 264 (same as above) is "pressed" into a signed char, turning it to 8. Applying >> 8 here results in 0.
Well, and your 3rd example, 2 >> 8 is obvously 0, so the 66 is left unchanged.

Related

Combining two 8-bit integers to a 16-bit integer

IN C Programming, how do I combine (note: not add) two integers into one big integer? So if i have
int a = 8
int b = 6
in binary it would be
int a = 1000
int b = 0110
so combined it would be = 01101000
You would use a combination of the << shift operator and the bitwise | operator. If you are trying to build an 8-bit value from two 4-bit inputs, then:
int a = 8;
int b = 6;
int result = (b << 4) | a;
If you are trying to build a 32-bit value from two 16-bit inputs, then you would write
result = (b << 16) | a;
Example:
#include <stdio.h>
int main( void )
{
int a = 8;
int b = 6;
printf( "a = %08x, b = %08x\n", (unsigned int) a, (unsigned int) b );
int result = (b << 4) | a;
printf( "result = %08x\n", (unsigned int) result );
result = (b << 8) | a;
printf( "result = %08x\n", (unsigned int) result );
result = (b << 16) | a;
printf( "result = %08x\n", (unsigned int) result );
return 0;
}
$ ./bits
a = 00000008, b = 00000006
result = 00000068
result = 00000608
result = 00060008
You can do it as follow using binary mask & 0x0F and bit translation <<:
int a = 0x08
int b = 0x06
int c = (a & 0x0F) + ((b & 0x0F) << 4 )
I hope that it helped
Update 1:
As mentionned in the comment addition + or binary or | are both fine.
What is important to highlight in this answer is the mask & 0x0F, I strongly recommand to use this kind of mecanism to avoid any overflow.
you could use or operator.
int a = 8 ;
int b = 6 ;
int c = (a << 8) | b;
You can use the bit-shift operator << to move the bits into the correct position:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main()
{
uint8_t a = 8;
uint8_t b = 6;
uint16_t c = (b << 4) | a;
printf( "The result is: 0x%" PRIX16 "\n", c );
}
This program will print the following:
The result is: 0x68
Note that this program uses fixed-width integer types, which are recommended in this situation, as you cannot rely on the size of an int or unsigned int to have a certain width.
However, there is no need for the result to be 16-bits, if you are only shifting one value by 4 bits, as you are doing in your example. In that case, an integer type with a width of 8-bits would have been sufficient. I am only using 16-bits for the result because you explicitly asked for it.
The macro PRIX16 will probably expand to "hX" or "X" on most platforms. But it is still recommended to use this macro when using fixed-width integer types, as you cannot rely on %hX or %X being the correct format specifier for uint16_t on all platforms.

Most efficient way to find an intersection between two sets of numbers encoded with bitwise operations

Given two sets of numbers encoded with bitwise operations (using 6 bits for number):
a = {12,20,21,24,31}
b = {13,18,24,28,35}
Intersection -> a ∩ b = {24}
unsigned int a = 0;
a |= (12 | 20 << 6 | 21 << 12 | 24 << 18 | 31 << 24);
unsigned int b = 0;
b |= (13 | 18 << 6 | 24 << 12 | 28 << 18 | 35 << 24);
What is the fastest way to find out, if there is at least one number in common between the sets?
This is just an example, but you can have common numbers in any position.
#include <stdint.h>
#include <limits.h>
typedef unsigned int SetType;
#define FieldWidth 6 // Number of bits per field.
#define NumberOfFields (sizeof(SetType) * CHAR_BIT / FieldWidth)
// Return non-zero iff some element is in both a and b.
int IsIntersectionNonEmpty(SetType a, SetType b)
{
// Create masks with a bit set for each element an input set.
uint64_t A = 0, B = 0;
for (int i = 0; i < NumberOfFields; ++i)
{
A |= UINT64_C(1) << (a >> i*6 & 0x3f);
B |= UINT64_C(1) << (b >> i*6 & 0x3f);
/* ">> i*6" moves field i to the low bits.
"& 0x3f" isolates that six-bit field.
"UINT64_C(1) << …" generates a 1 bit in that position.
*/
}
/* Bitwise AND A and B to see if they have a bit in common, then
convert that to 1 or 0.
*/
return !! (A & B);
}
Maybe not the absolute fastest, but I'd XOR a with b, and see if the result has any six-bit all-zeros pattern in any of your 5 positions. Then shift one of them by 6 bits and repeat up to 4 more times if needed.
Here's a somewhat faster version of my solution above; instead of shifting left and right, just rotate:
int leftRotate(unsigned int n, unsigned int d)
{
return (n << d)|(n >> (32 - d));
}
// Return non-zero iff some element is in both a and b.
int IsIntersectionNonEmpty(unsigned int a, unsigned int b)
{
for (int i = 0; i < 5; i++) {
unsigned int matches = leftRotate(a, i*6) ^ b;
for (int j = 0; j < 5; j++) {
unsigned int testval = 0x3f << j*6;
if (matches & testval == testval)
return 1; // success
}
}
return 0;
}
5 instructions in the outer loop, 3 in the inner * 5, so 20 total, times 5 loops, around 100 instructions total -- but as soon as it finds a match it returns. So if there are frequent matches it'll likely be faster than the #eric-postpischil version, but with no matches it'll be slower. On the other hand, his solution is likely auto-vectorizable with a smart compiler.
Well, thanks to everyone, but thank to the guy that posted the EL code, I do not know why he withdrew it.
Here we go, as fast as light:
#define EL(x) (UINT64_C(1) << (x))
unsigned int a = 0;
a |= (12 | 20 << 6 | 21 << 12 | 24 << 18 | 31 << 24);
unsigned int b = 0;
b |= (13 | 18 << 6 | 24 << 12 | 28 << 18 | 35 << 24);
unsigned int aa = EL(a & 0x00000003F) | EL((a & 0x000000FC0) >> 6) | EL((a & 0x3F000) >> 12) | EL((a & 0xFC0000) >> 18) | EL((a & 0x3F000000) >> 24);
unsigned int bb = EL(b & 0x00000003F) | EL((b & 0x000000FC0) >> 6) | EL((b & 0x3F000) >> 12) | EL((b & 0xFC0000) >> 18) | EL((b & 0x3F000000) >> 24);
anb = !! (aa & bb); // intersection

XOR certain bytes in c

I am wondering if anyone can help me. I am new to c and only learning. So this questain may seem confused. I have an unsigned int value that I need to split into bytes then xor certain bytes together and then get the result. I want represent the value as (0, a0 ⊕ a1,a2 ⊕a3,0).
Decimal value = 62910759 or Hex value = 3BFF127;
unsigned int value = 62910759;
// W = (0, a0 ⊕ a1,a2 ⊕a3,0);
unsigned int L = 0x04000000L^ W ;
I don't know if this helps you, but i calculate the bytes first and then XOR some of them:
unsigned int value = 62910759;
unsigned char a = value >> 24 & 0xFF; // First byte/ high byte
unsigned char b = value >> 16 & 0xFF;
unsigned char c = value >> 8 & 0xFF;
unsigned char d = value & 0xFF; // Last byte/ smallest byte
printf("%.2X %.2X %.2X %.2X\n", a,b,c,d);
unsigned char aXORb = a^b; // a XOR b
unsigned char bXORc = b^c;
unsigned char cXORd = c^d;
unsigned char dXORa = d^a;
printf("%.2X %.2X %.2X %.2X\n", aXORb,bXORc,cXORd,dXORa);
Try it here.
Output:
03 BF F1 27
BC 4E D6 24
Note: I think uint8_t would be more "C-like" but the result will be the same anyway.
#Jimbo Jones Here is the last step. The zeros are unnecessary, but i included them for better understanding the code.
unsigned int result = (0x00 << 24) + (aXORb << 16) + (cXORd << 8) + 0x00;
Method(0x02000000L^ result);
If you mean with W = (0, a0 ⊕ a1,a2 ⊕a3,0) that the first 8 bit are 0 and the next 8 a XOR b and so on.

Unexpected result after chaining bit-shift operators in C

I can't figure out why chaining bit-shift operations is not returning the same result as not chaining them.
#include <stdio.h>
void bit_manip_func(unsigned char byte)
{
unsigned char chain = (((byte >> 3) << 7) >> 3);
printf("%d\n", chain); //this prints 144
unsigned char o1 = byte >> 3;
unsigned char o2 = o1 << 7;
unsigned char o3 = o2 >> 3;
printf("%d\n", o3); //this prints 16 as expected
}
int main()
{
//expecting both printf's to print
//the same value (16).
bit_manip_func(73);
return 0;
}
I'm expecting both printf calls to print out 16 since 73 in binary is 0100 1001. After applying byte >> 3 I should get 0000 1001, after (byte >> 3) << 7 the result should be 1000 0000, and after (((byte >> 3) << 7) >> 3) the result should be 0001 0000, which of course is 16. What's actually happening?
The operators >> and << perform integer promotions on their operands. Thus the type unsigned char is promoted to int, when used with either operator.
In the following line, the variable byte is promoted to type int, and then all three operations are performed on this type:
unsigned char chain = (((byte >> 3) << 7) >> 3);
The left most bit set to one is thus preserved:
01001001 => 01001 => 010010000000 => 010010000
^ ^ ^ ^
In the following code, the variables are promoted to type int, but after each operation, the result, which has the type int, is assigned to an unsigned char and thus wraps (most significant bits are removed),
since the range of unsigned char is [ 0 , 2^8-1 ] on your platform.
unsigned char o1 = byte >> 3;
unsigned char o2 = o1 << 7;
unsigned char o3 = o2 >> 3;
This means that the left most bit set to one is not preserved:
01001001 => 01001 => 10000000 => 000010000
^ ^
In
unsigned char chain = (((byte >> 3) << 7) >> 3);
((byte >> 3) << 7) is promoted to an int, then it performs >> 3 over the int
Wrapped to an unsigned char (mod 256) you get ((73 >> 3) << 7) >> 3) % 256 = 144
Use a cast:
unsigned char chain = ((unsigned char)((byte >> 3) << 7) >> 3);

RGB color converting into 5:6:5 format

This code is supposed to convert a RGB color to an hex in the 5:6:5 format. 5 bits for red, 6 bits for green, 5 bits for blue. I have no idea why this is not picturing the correct color.
Does anyone knows why?
int rgb(unsigned char r, unsigned char g, unsigned char b) {
if (r < 0 || 255 < r || g < 0 || 255 < g || b < 0 || b > 255)
return -1;
int result;
int red = r * 31 / 255;
int green = g * 63/ 255;
int blue = b * 31 / 255;
//int result = (red << 11) | (green << 5) | blue;
green = green << 5;
red = red << 11;
result = red | green | blue;
//tests
printf("\nred: %x", red);
printf("\ngreen: %x", green);
printf("blue: %x\n", blue);
printf("result: %x\n", result);
return result;
}
After another look at your question I don't really know what you're asking about. Anyway, I'm leaving my answer in case you find it useful.
Your rgb(...) function takes three byte arguments - they have 8 bits each.
Let's take "red" component into account first. If you pass XXXX XXXX (8 bits) and want to convert them into a 5-bit equivalent representation, it's enough to shift the value right by 3 bits, so:
int red = r >> 3;
The value XXXXXXXX will be truncated in the place of the pipeline character:
XXXXX|xxx
so that only the bits marked with large Xes will be saved to the red variable.
The same goes for blue, and for the green component, you have to shift it right by two (8 - 6 = 2).
You probably want your function to work like this:
int rgb(unsigned char r, unsigned char g, unsigned char b) {
if (r < 0 || 255 < r || g < 0 || 255 < g || b < 0 || b > 255)
return -1;
unsigned char red = r >> 3;
unsigned char green = g >> 2;
unsigned char blue = b >> 3;
int result = (red << (5 + 6)) | (green << 5) | blue;
//tests
printf("red: %x\n", red);
printf("green: %x\n", green);
printf("blue: %x\n", blue);
printf("result: %x\n", result);
return result;
}
Assuming 8-bit char, your unsigned char arguments must already be in the 0-255 range, so you don't need to check that. And the multiplication you're trying to use to scale the color components is probably not a good approach.
A better approach would be to AND each component with a mask to get the upper 5 bits (6 for green), shift them to the proper positions, and OR them together. When shifting, remember to account for the fact that you're using the upper bits... and for the last component, you won't need to AND with a mask because the unneeded bits are shifted out anyway. So this gets you something like this (as the only line in your function):
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
(r & 0xf8) gets the upper 5 bits of r. These are then left shifted by 8 bits, so they move from positions 3..7 into 11..15.
(g & 0xfc) gets the upper 6 bits of g. Those are then left shifted by 3 bits, from 2..7 into 5..10.
b doesn't need to be masked... it's just shifted right 3 bits. Its upper 5 bits are then moved from 3..7 into 0..4, and its lower 3 bits are discarded when they're shifted out.
All those values are then ORed together to get your RGB 5:6:5 value, and returned.
Alternatively, if you prefer shifts over AND, you can use:
return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
You might also consider changing the return type to an unsigned 16-bit type and not worry about returning an error value (there isn't really any kind of error condition to check for here).
You need a function that shows you the binary contents, so that you can "count" the bits and better find errors. My approach added a rounding routine:
#include <stdio.h>
#include <math.h>
char* sprint_bin (unsigned a, unsigned count, char* bin)
{
char* p = bin;
unsigned i;
unsigned mask = pow(2,count-1);
unsigned b;
for (i = 0; i<count; ++i)
{
b = (a & mask) ? '1' : '0';
p += sprintf (p, "%c ",b);
mask >>= 1;
}
return bin;
}
unsigned rgb(unsigned char r, unsigned char g, unsigned char b) {
char bin[64];
int result;
printf("r: %s\n", sprint_bin(r,8,bin));
printf("g: %s\n", sprint_bin(g,8,bin));
printf("b: %s\n", sprint_bin(b,8,bin));
// masks
unsigned red = (unsigned)(r & 0xF8) << 8;
unsigned green = (unsigned)(g & 0xFC) << 3;
unsigned blue = (unsigned)(b >> 3);
// rounding
if ((r & 4) && (r<0xF8)) red += 0x0800;
if ((g & 2) && (g<0xFC)) green += 0x20;
if ((b & 4) && (b<0xF8)) blue++;
// 5:6:5
result = red | green | blue;
// test
printf("red: %s\n", sprint_bin(red,16,bin));
printf("green: %s\n", sprint_bin(green,16,bin));
printf("blue: %s\n", sprint_bin(blue,16,bin));
printf("result: %s\n", sprint_bin(result,32,bin));
return result;
}
int main ()
{
rgb (0x81, 0x87, 0x9F);
return 0;
}

Resources