How to divide an Int into two Bytes in C?

Clash Royale CLAN TAG#URR8PPPHow to divide an Int into two Bytes in C?
I am working with software embedded in minimal hardware that only supports ANSI C and has minimal versions of the standard IO libraries.
I have an Int variable, two bytes in size, but I need to divide it into 2 bytes separately to be able to transmit it, and then I can, reading the two bytes, reassemble the original Int.
I can think of some binary division of each byte like this:
int valor = 522; // 0000 0010 0000 1010 (entero de 2 bytes)
byte superior = byteSuperior(valor); // 0000 0010
byte inferior = byteInferioror(valor); // 0000 1010
...
int valorRestaurado = bytesToInteger(superior, inferior); // 522
but I do not succeed in a simple way of dividing the whole by its weight and it gives me the feeling that it should be trivial (such as with bit shifting) and I do not discover it.
Actually, any solution that divides the whole into 2 bytes and reassembles it serves me well.
From already thank you very much!
htons()
ntohs()
htons()
int
ntohs()
5 Answers
5
You can get the bytes using simple bit shift operations:
#define HI_BYTE(val) (((val)>>8)&0xFF)
#define LO_BYTE(val) ((val)&0xFF)
unsigned in val = 512;
unsigned char lo = LO_BYTE(val);
unsigned char hi = HI_BYTE(val);
And you can combine them again:
unsigned int val = ((unsigned int)hi)<<8 | lo;
This isn't a "simple" task.
First of all, the data type for a byte in C is char. You probably want unsigned char here, as char can be either signed or unsigned, it's implementation-defined.
char
unsigned char
char
int is a signed type, which makes right-shifting it implementation-defined as well. As far as C is concerned, int must have at least 16 bits (which would be 2 bytes if char has 8 bits), but can have more. But as your question is written, you already know that int on your platform has 16 bits. Using this knowledge in your implementation means your code is specific to that platform and not portable.
int
int
char
int
As I see it, you have two options:
You can work on the value of your int using masking and bit-shifting, something like:
int
int foo = 42;
unsigned char lsb = (unsigned)foo & 0xff; // mask the lower 8 bits
unsigned char msb = (unsigned)foo >> 8; // shift the higher 8 bits
This has the advantage that you're independent of the layout of your int in memory.
int
You can use the representation in memory, like:
int foo = 42;
unsigned char *rep = (unsigned char *)&foo;
unsigned char first = rep[0];
unsigned char second = rep[1];
But beware whether first will be the MSB or LSB depends on the endianness used on your machine. Also, if your int contains padding bits (extremely unlikely in practice, but allowed by the C standard), you will read them as well.
first
int
You can actually, cast the address of the integer variable to a char *, read the value and then increment the pointer to point to the next byte to read the value again. This conforms with the aliasing rules.
char *
I am using int shrot instead of int to dry, because on the PC the int are 4 bytes and on my target platform they are 2. Use unsigned to make it easier to debug.
The code compiles with GCC (and should do it with almost any other C compiler). If Im not wrong, it depends on whether the architecture is big endian or little endian, but it would be solved by inverting the line that reconstructs the integer:
big endian
little endian
#include <stdio.h>
void main(){
// unsigned short int = 2 bytes in a 32 bit pc
unsigned short int valor;
unsigned short int rearmado;
unsigned char data0 = 0;
unsigned char data1 = 0;
printf("An integer is %d bytesn", sizeof(valor));
printf("Enter a number: n");
scanf("%d",&valor);
// Decomposes the int in 2 bytes
data0 = (char) 0x00FF & valor;
data1 = (char) 0x00FF & (valor >> 8);
// Just a bit of 'feedback'
printf("Integer: %d n", valor);
printf("Hexa: %X n", valor);
printf("Byte 0: %d - %X n", data0, data0);
printf("Byte 1: %d - %X n", data1, data1);
// Rebuild the int from 2 bytes
rearmado = (unsigned short int) (data1 << 8 | data0);
// Show the rebuilt int
printf("Rebuilt Integer: %d n", rearmado);
printf("Rebuilt Hexa: %X n", rearmado);
return;
}
I wouldn't even write functions to do this. Both operations are straightforward applications of C's bitwise operators:
int valor = 522; // 0000 0010 0000 1010 (entero de 2 bytes)
unsigned char superior = (valor >> 8) & 0xff;
unsigned char inferior = valor & 0xff;
int valorRestaurado = (superior << 8) | inferior;
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Are you sending the data from one system to another that has different endianness? If so, you can use
htons()andntohs()if they're available on your systems. You usehtons()to convert a two-byteintvalue to network byte order, then on receiving it you usentohs()to convert it back to the host byte order for the host you received it on.– Andrew Henle
25 mins ago