How to divide an Int into two Bytes in C?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


How 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!





Are you sending the data from one system to another that has different endianness? If so, you can use htons() and ntohs() if they're available on your systems. You use htons() to convert a two-byte int value to network byte order, then on receiving it you use ntohs() to convert it back to the host byte order for the host you received it on.
– Andrew Henle
25 mins ago




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.

Popular posts from this blog

Arduino Mega cannot recieve any sketches, stk500_recv() programmer is not responding

Visual Studio Code: How to configure includePath for better IntelliSense results

C++ virtual function: Base class function is called instead of derived