Packing two 8-bit values - c

I am stuck with a simple problem. Here is the code:
int main(int argc, char **argv)
{
char buf[2] = {0xd, 0x1f};
unsigned int a;
a = ((buf[1] << 8) & 0xFF00) | buf[0];
printf("%d\n",a);
return 0;
}
The value in a that I need is 0x1FD(509) but when I ran the above program the output in a is 0x1F0D(7949) .
How can I achieve this ?
EDIT :
Ok let me clarify . I am doing a project where I receive the data as shown in the code snippet.To simplify I have declared them local . The main thing is I want the data to be interpreted as 0x1FD(509) .

The program does what you asked it to do. The source of your confusion is in the 0xd constant, which is actually 0x0d, because char is eight bits. Packing it together with 0x1f as you do should produce 0x1f0d, and it does.

You need
char buf[2] = {0xfd, 0x01};
That is, you need to "pack" the bits from right to left.
This is clearer if you pad the desired value with zeroes, so it's written as a string of complete bytes:
0x1FD = 0x01FD = (0x01 << 8) | 0xFD

A char is 8 bits, hence it is represented by two hexadecimal digits.
If you want 0x1FD in your variable a, then you should initialize the array with 0xfd and 0x01.

You need to remove the empty bits:
unsigned pack(char bytes[2])
{
char shift = 8;
if (bytes[0] < 32)
shift = 4;
return (unsigned) ((bytes[1] << shift) | bytes[0]);
}

Related

How to shift bytes from char array into int

I would like to make a int varibale out of a char array in C.
The char array looks like this:
buffer[0] = 0xcf
buffer[1] = 0x04
buffer[2] = 0x00
buffer[3] = 0x00
The shifting looks like this
x = (buffer[1] << 8 )| (buffer[0] << 0) ;
After that x looks like this:
x = 0xffff04cf
Right now everthing would be fine, if the first two bytes wouldn't be ff.
If I try this line
x = (buffer[3] << 24 )| (buffer[2] << 16)| (buffer[1] << 8)| (buffer[0] << 0) ;
it still looks
x = 0xffff04cf
Even when I try to shift in the zeros before or after I shift in 04cf it looks still the same.
Is this the rigth idea to it or what am I doing wrong?
The issue is that you declared buffer by means of a signed type, probably (signed) char. When applying operator <<, integral promotions will be performed, and as the value 0xcf in an 8-bit signed type represents a negative value (i.e. -49), it will remain a negative value (yet represented by more bits, i.e. 0xffffffcf). Note that -1 is represented as 0xFFFFFFFF and vice versa.
To overcome this issue, simply define buffer as
unsigned char buffer[4]
And if you weren't allowed to change the data type of buffer, you could write...
unsigned x = ( (unsigned char)buffer[0] << 8 )| ((unsigned char)buffer[1] << 4) ;
For tasks like this I like using unions, for example:
union tag_int_chars {
char buffer[sizeof(int32_t)];
int32_t value;
} int_chars;
int_chars.value = 0x01234567;
int_chars.buffer[0] = 0xff;
This will automate the memory overlay without the need to shift. Set the value of the int and voila the chars have changed, change a char value and voila the int has changed.
The example will leave the int value = 0x012345ff on a little endian machine.
Another easy way is to use memcpy():
#include <string.h>
char buffer[sizeof(int32_t)];
int32_t value;
memcpy(&value, buffer, sizeof(int32_t)); // chars to int
memcpy(buffer, &value, sizeof(int32_t)); // int to chars

Convert 2 bytes into an integer

I receive a port number as 2 bytes (least significant byte first) and I want to convert it into an integer so that I can work with it. I've made this:
char buf[2]; //Where the received bytes are
char port[2];
port[0]=buf[1];
port[1]=buf[0];
int number=0;
number = (*((int *)port));
However, there's something wrong because I don't get the correct port number. Any ideas?
I receive a port number as 2 bytes (least significant byte first)
You can then do this:
int number = buf[0] | buf[1] << 8;
If you make buf into an unsigned char buf[2];, you can simplify it to:
number = (buf[1] << 8) + buf[0];
I appreciate this has already been answered reasonably. However, another technique is to define a macro in your code eg:
// bytes_to_int_example.cpp
// Output: port = 514
// I am assuming that the bytes the bytes need to be treated as 0-255 and combined MSB -> LSB
// This creates a macro in your code that does the conversion and can be tweaked as necessary
#define bytes_to_u16(MSB,LSB) (((unsigned int) ((unsigned char) MSB)) & 255)<<8 | (((unsigned char) LSB)&255)
// Note: #define statements do not typically have semi-colons
#include <stdio.h>
int main()
{
char buf[2];
// Fill buf with example numbers
buf[0]=2; // (Least significant byte)
buf[1]=2; // (Most significant byte)
// If endian is other way around swap bytes!
unsigned int port=bytes_to_u16(buf[1],buf[0]);
printf("port = %u \n",port);
return 0;
}
Least significant byte:
int number = (uint8_t)buf[0] | (uint8_t)buf[1] << 8;
Most significant byte:
int number = (uint8_t)buf[1] << 8 | (uint8_t)buf[0];
char buf[2]; //Where the received bytes are
int number;
number = *((int*)&buf[0]);
&buf[0] takes address of first byte in buf.
(int*) converts it to integer pointer.
Leftmost * reads integer from that memory address.
If you need to swap endianness:
char buf[2]; //Where the received bytes are
int number;
*((char*)&number) = buf[1];
*((char*)&number+1) = buf[0];

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);

32 bit hex in one variable

How can I put this hex 0x0a01 into a 32 bit var in C. What I'm trying to do is to parse a protocol. Part of the it has a length value. The problem is that I'm getting the received packet as an array, so the length 0x0a01 would be 0x0a on lets say [1] and 0x01 on [2], and I want them both to be 0a01 in one var so I can run a compare to a constant or use in a for loop.
ah 32 bit is a int in most current platforms (or int32_t defined in stdint.h)
and bit operations are made for this:
int var = buff[1]<<8|buff[2];
<< is the left shift so 0x0a gets transformed into 0x0a00 and | is the or operator so that is gets combined properly
uint32_t var;
char buff[128];
...
var = ((buff[1] & 0xFF) << 8) | (buff[2] & 0xFF);
Notice we use (buff[1] & 0xFF) << 8 and not buff[1] << 8, because if buff is a char array and char is signed, sign extension would occur on the promoted buff[1] when the value is negative.

Resources