Reputation: 21
I am pretty new in c programming and I am trying to figure out more about bits, binary e.c.t
For example, I have three int variables m1 =255 or 11111111 in binary; m2 =255 or 11111111 in binary, m3 = 255 or 11111111 in binary and m4 =0 or 00000000. I am trying to put all theme together into single int variable temp. Something like this (11111111 11111111 11111111 00000000) Here is the piece of code that I have:
int x1;
unsigned char x2;
unsigned char x3;
unsigned char x4;
int temp;
x1 = x1|m1;
printf("x1:%d\n", x1);
x2 = x2|m2;
printf("x2:%d\n", x2);
temp = x1<<8;
printf("temp:%d\n", temp);
temp = temp|x2;
printf("temp:%d\n", temp);
x3 = x3|m3;
printf("x3:%d\n", x3);
temp = temp<<8;
printf("temp:%d\n", temp);
temp = temp|x3;
printf("temp:%d\n", temp);
x4 = x4|m4;
printf("x4:%d\n", x4);
temp = temp<<8;
printf("temp:%d\n", x1);
temp = temp|x4;
printf("%d\n", temp);
I am using left shift and OR operators here. But I got a little bit wierd output. (I printed out every to step to find out what is wrong).
I got next output:
x1:255
x2:255
temp:65280
temp:65535
x3:255
temp:16776960
temp:16777215
x4:0
temp:-256
temp:-256
Everything goes fine until temp becomes -256 and I do not know why. I appreciate any help! Thank you!
Upvotes: 1
Views: 1273
Reputation: 84569
You really have a couple of choices in C. First, what it appears you are attempting to do is the following. (note: you should include stdint.h
and use uint32_t
guaranteed width values instead of int
) Your problems surround invoking Undefined Behavior by OR'ing uninitialized values, and failing to properly shift the values for x1, ..., x4
.
To do what it looks like you are attempting to do, you could:
#include <stdio.h>
int main (void) {
unsigned int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
unsigned char m1, m2, m3, m4 = 0;
m1 = m2 = m3 = 255;
x1 |= m1;
x2 |= ((unsigned)m2 << 8);
x3 |= ((unsigned)m3 << 16);
x4 = ((x1 | x2 | x3) << 8) | (unsigned)m4;
printf("x1: %u\n", x1);
printf("x2: %u\n", x2);
printf("x3: %u\n", x3);
printf("x4: %u\n", x4);
return 0;
}
Example Use/Output
$ ./bin/shiftx
x1: 255
x2: 65280
x3: 16711680
x4: 4294967040
You can also simplify your logic by simply using a two variables and the value 255
. Essentially, you are setting your temp variable to 255
and shifting left by 8, 3-times. Your final value is the OR'ing of the first 3 temp values with a final shift by 8 to get your combined value with the least significant byte zero, e.g.
#include <stdio.h>
#include <stdint.h>
int main (void) {
uint32_t tmp = 0, val = 0;
uint8_t m = 255;
val = m;
printf ("tmp1 : %u\n", val);
tmp = val << 8;
printf ("tmp2 : %u\n", tmp);
val |= tmp;
tmp <<= 8;
printf ("tmp3 : %u\n", tmp);
val |= tmp;
tmp <<= 8;
printf ("tmp4 : %u\n", tmp);
val <<= 8;
printf ("val : %u\n", val);
return 0;
}
Example Use/Output
$ ./bin/shift1var
tmp1 : 255
tmp2 : 65280
tmp3 : 16711680
tmp4 : 4278190080
val : 4294967040
An improved version could make use of a union
between a bitfield struct
and a uint32_t
value, guaranteeing a 32-bit
width regardless of architecture. For example, you could:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct {
uint32_t a : 8,
b : 8,
c : 8,
d : 8;
} bits;
uint32_t value;
} bitunion;
int main (void) {
bitunion bu = { .bits = {.a = 0, .b = 255, .c = 255, .d = 255} };
printf ("bu.bits.a: %u\n", bu.bits.a);
printf ("bu.bits.b: %u\n", bu.bits.b << 8);
printf ("bu.bits.c: %u\n", bu.bits.c << 16);
printf ("bu.bits.d: %u\n", bu.bits.d << 24);
printf ("value : %u\n", bu.value);
return 0;
}
(note: the bitfield is made up of d-c-b-a
bytes)
Example Use/Output
$ ./bin/shiftxstruct
bu.bits.a: 0
bu.bits.b: 65280
bu.bits.c: 16711680
bu.bits.d: 4278190080
value : 4294967040
Now, don't think these are the only ways to do this. You can use any combination of shifts and OR's as long as you accurately account for the bytes within your final value. Look things over and let me know if you have additional questions.
Upvotes: 1
Reputation: 116
You're using %d format and it treats variables as signed integers, you need to use %u and change the variable types to unsigned.
unsigned char x1;
unsigned int temp;
Upvotes: 1