combining variables using bitwise operators - c

I need a function that takes four unsigned char variables as parameters and combines them into an unsigned int. The first char variable being the first byte of the int, the second char being the second byte and so on. Here is what I have so far, it is not working properly and I can't figure out why after messing around with it and googling for several hours.
uint32_t combineChar(unsigned char one, unsigned char two, unsigned char three, unsigned char four){
uint32_t com;
com = (uint32_t)one;
com = com << 8 | (uint32_t)two;
com = com << 8 | (uint32_t)three;
com = com << 8 | (uint32_t)four;
return com;
}

Your code is endianess-depend. The first byte (of uint32_t) is in some systems the leftest, and in some systems the rightest, so you may store the bytes in the opposite way than what to you want.
(Actually, if you want just the uint32_t, it's fine. Problems begin when you union it with char[4], or similar stuff)

Check the precedence of the "<<" and "|" operators.
uint32_t combineChar(unsigned char one, unsigned char two
, unsigned char three, unsigned char four){
return one | (two << 8) | (three << 16) | (four <<24);
}

Related

Bit Operation in C

I am new in C and this is for a school project. I am implementing the Skinny Block Cipher in C.
My code:
unsigned char *bits[8]; // this array holds 1 byte of data.
... call in another func to convert hex to bit.
unsigned int four = bits[4] - '0'; // value 0
unsigned int seven = bits[7] - '0'; // value 1
unsigned int six = bits[6] - '0'; // value 1
four = four ^ ~(seven | six); // eq 1;
Now, my question
Do I have to convert the char to int every time to run the bit operation? What will happen if I do it using unsigned char?
If I store the value for eq - 1 on an unsigned int, the value is fe which is wrong (according to an online bit calculator), on the other hand, if I store the result in an unsigned char, the value is -2 which is correct. What's the difference? I am kind of lost here.
bits[8] is a pointer and I tried to do the eq 1 using indexes from bits pointer, like bits[4], etc but my VSCode throws an error and I don't understand why. Obviously, I have some gaps in my knowledge. I am using my Python knowledge to go through this.
I don't know if I am giving all the information that's needed. Hit me up for extras!
TIA.
I updated the code
unsigned char bits[9];
It converts a3 into 010100011.
unsigned char *bits[8]; // this array holds 1 byte of data.
No, it is an array of 8 pointers to char.
unsigned int four = bits[4] - '0'; // value 0
This will not work as you subtract the integer '0' from the pointer.
If you want to keep the string representation of the number in the binary form you need to define an array of 9 chars
char bits[9] = "10010110";
Then you can do the operations as in your code.
Do I have to convert the char to int every time to run the bit
operation? What will happen if I do it using unsigned char?
If you want to keep it as a string then - yes.
unsigned char x = 0x96;
unsigned int four = !!(x & (1 << 4));
unsigned int seven = !!(x & (1 << 7));
unsigned int six = !!(x & (1 << 6));

Cast char subarray to integer

unsigned int b;
unsigned char a[] =
{0x00,0x00,0x00,0x12,0x00,0x00,0x81,0x03,0x00,0x00,0x00,0x00,0x01,0x91,0x01,0x01,0xb1,0x04,0x47,0x86,0x8f,0xf8,0x00};
I'm a newbie in C programming,
I need to take the 4 bytes subarray start at a[18] which is 0x47868ff8,
and cast it into corresponding decimal integer:1200001016.
I try to use memcpy(&b,a+18, 4), but it does not seem to work,
Could anyone give me some hints to work out this function?
And if I want to read a char pointer message then cast per 4 bytes in order into integer array,
what is the best way to do that? Thanks.
Copying like that has implementation-defined behavior, and you'll get different results depending on the endianness of the CPU.
To do it portably you can use bitwise operations.
b = (unsigned int)a[18] << 24 | (unsigned int)a[19] << 16 | (unsigned int)a[20] << 8 | a[21];

Combined 3 unsigned chars into an unsigned int

I have a requirement to have an unsigned 3 byte type in C. I am looking for a way to pack them into a single unsigned int.
Is this safe or does this need to be stored inside an array/structure for the 24 bit size?
unsigned int pack_3Byte(unsigned char b1, unsigned char b2, unsigned char b3)
{
return (b1 << 16) | (b2 << 8) | (b3);
}
Your code is correct but like Olaf says you should use the types uint8_t and uint32_t to ensure that your types are really the width you expect them to be.
This may not be a problem right now, but you should also be aware that the bytes in an integer are stored in different order on different processors. This is called endianness.

How do I convert and break a 2 byte integer into 2 different chars in C?

I want to convert an unsigned int and break it into 2 chars. For example: If the integer is 1, its binary representation would be 0000 0001. I want the 0000 part in one char variable and the 0001 part in another binary variable. How do I achieve this in C?
If you insist that you have a sizeof(int)==2 then:
unsigned int x = (unsigned int)2; //or any other value it happens to be
unsigned char high = (unsigned char)(x>>8);
unsigned char low = x & 0xff;
If you have eight bits total (one byte) and you are breaking it into two 4-bit values:
unsigned char x=2;// or whatever
unsigned char high = (x>>4);
unsigned char low = x & 0xf;
Shift and mask off the part of the number you want. Unsigned ints are probably four bytes, and if you wanted all four bytes, you'd just shift by 16 and 24 for the higher order bytes.
unsigned char low = myuint & 0xff;
unsigned char high = (myuint >> 8) & 0xff;
This is assuming 16 bit ints check with sizeof!! On my platform ints are 32bit so I will use a short in this code example. Mine wins the award for most disgusting in terms of pulling apart the pointer - but it also is the clearest for me to understand.
unsigned short number = 1;
unsigned char a;
a = *((unsigned char*)(&number)); // Grab char from first byte of the pointer to the int
unsigned char b;
b = *((unsigned char*)(&number) + 1); // Offset one byte from the pointer and grab second char
One method that works is as follows:
typedef union
{
unsigned char c[sizeof(int)];
int i;
} intchar__t;
intchar__t x;
x.i = 2;
Now x.c[] (an array) will reference the integer as a series of characters, although you will have byte endian issues. Those can be addressed with appropriate #define values for the platform you are programming on. This is similar to the answer that Justin Meiners provided, but a bit cleaner.
unsigned short s = 0xFFEE;
unsigned char b1 = (s >> 8)&0xFF;
unsigned char b2 = (((s << 8)>> 8) & 0xFF);
Simplest I could think of.
int i = 1 // 2 Byte integer value 0x0001
unsigned char byteLow = (i & 0x00FF);
unsinged char byteHigh = ((i & 0xFF00) >> 8);
value in byteLow is 0x01 and value in byteHigh is 0x00

bitwise operations in C receiving binary in a char

I am receiving 2 bytes of binary information via Serial in C.
I am receiving them in a char.
So I need to join the 2 chars to make a int but Im unsure how to do that.. first of all the first byte is in binary format and not char format.. So im unsure how I Can convert it into a useable form for my program.
Just OR them together ?
x = (b1 << 8) | b2;
Make sure they're unsigned or cast accordingly (shifting signed stuff is nasty).
You can use something like this:
int my_int=char1;
myint<<=8;
myint|=char2;
This assumes char1 contains the most significant byte. Switch the 1 and 2 otherwise.
use unsigned char to avoid sign-extension problems.
val16 = char1 * 256 + char2;
For a start, it would be better to receive them in an unsigned char just so you have no issues with sign extension and the like.
If you want to combine them, you can use something like:
int val = ch1; val = val << 8 | ch2;
or:
int val = ch2; val = val << 8 | ch1;
depending on the endian-ness of your system, and assuming your system has an eight-bit char type.
if MSB (Most Significant Byte) comes first:
unsigned char array[2];
...
int bla;
bla = array[1] | (array[0] << 8);
if LSB (Least Significant Byte) comes first:
bla = array[0] | (array[1] << 8);

Resources