newbie question.
Say for example, I have the hex number 0xABCDEF, how would i split it into 0xAB,0xCD and 0xEF?
Is it like this?
unsigned int number = 0xABCDEF
unsigned int ef = a & 0x000011;
unsigned int cd = (a>>8) & 0x000011;
unsigned int ab = (a>>16) & 0x000011;
Thanks
Use 0xff as your mask to remove all but 8 bits of a number:
unsigned int number = 0xABCDEF
unsigned int ef = number & 0xff;
unsigned int cd = (number>>8) & 0xff;
unsigned int ab = (number>>16) & 0xff;
unsigned int number = 0xABCDEF
unsigned int ef = number & 0xff;
unsigned int cd = (number >> 8) & 0xff;
unsigned int ab = (number >> 16) & 0xff;
Instead of the bitwise and (&) operation, you might intead want ef, cd, ab to be unsigned char types, depending on the rest of your code and how you're working with these variables. In which case you cast to unsigned char:
unsigned int number = 0xABCDEF
unsigned char ef = (unsigned char) number;
unsigned char cd = (unsigned char) (number >> 8);
unsigned char ab = (unsigned char) (number >> 16);
The mask to use would be 0xFF, not 0x11. Apart of this, you are right.
void splitByte(unsigned char * split, unsigned int a,int quantBytes)
{
unsigned char aux;
int i;
for(i=0;i<quantBytes;i++)
{
split[i]=a&0x00FF;
a=(a>>8);
}
for(i=0;i<quantBytes-1;i++)
{
aux = split[i];
split[i] = split[quantBytes-i-1];
split[quantBytes-i-1] = aux;
}
}
In the main:
unsigned char split[4];
splitByte(split, 0xffffffff, 4);
Related
For example, I have two digit bits:
0b0111111
0b0000110
I want to shift a state variable by 7 digits and combine them together.
0b00001100111111
Can I accomplish by shifting?
You do this by shifting the bottom number left 7 digits, then performing a bitwise OR of the result and the first number.
unsigned int a = 0x3f;
unsigned int b = 0x06;
unsigned int result = (b << 7) | a;
unsigned int X = 0b00111111;
unsigned int Y = 0b00000110;
unsigned int Z = ((X << 7) & 0xFF00) | Y;
unsigned char a = 0b00000110;
unsigned char b = 0b01111111;
unsigned short c = (b << 8); // shift everything left 8 bits to set the high bits
c &= 0xFF00; // clear out the lower bits - not necessary in C
c |= a; // set the lower 8 bits
int a = 0b0111111;
int b = 0b0000110;
int combined = (a << 7) | b;
What is the FASTEST way, using bit operators to return the number, represented with 3 different unsigned char variables ?
unsigned char byte1 = 200;
unsigned char byte2 = 40;
unsigned char byte3 = 33;
unsigned long number = byte1 + byte2 * 256 + byte3 * 256 * 256;
is the slowest way possible.
Just shift each one into place, and OR them together:
#include <stdint.h>
int main(void)
{
uint8_t a = 0xAB, b = 0xCD, c = 0xEF;
/*
* 'a' must be first cast to uint32_t because of the implicit conversion
* to int, which is only guaranteed to be at least 16 bits.
* (Thanks Matt McNabb and Tim Čas.)
*/
uint32_t i = ((uint32_t)a << 16) | (b << 8) | c;
printf("0x%X\n", i);
return 0;
}
Do note however, that almost any modern compiler will replace a multiplication by a power of two with a bit-shift of the appropriate amount.
The fastest way would be the direct memory writing, assuming you know the endian of your system (here the assumption is little endian):
unsigned char byte1 = 200;
unsigned char byte2 = 40;
unsigned char byte3 = 33;
unsigned long number = 0;
((unsigned char*)&number)[0] = byte1;
((unsigned char*)&number)[1] = byte2;
((unsigned char*)&number)[2] = byte3;
Or if you don't mind doing some excercise, you can do something like:
union
{
unsigned long ulongVal;
unsigned char chars[4]; // In case your long is 32bits
} a;
and then by assigning:
a.chars[0] = byte1;
a.chars[1] = byte2;
a.chars[2] = byte3;
a.chars[3] = 0;
you will read the final value from a.ulongVal. This will spare extra memory operations.
Can you explain about how to convert the last 3 bytes of data from unsigned integer to a character array?
Example:
unsigned int unint = some value;
unsigned char array[3];
It's more difficult if you have to convert it to an array, but if you just want to access the individual bytes, then you can do
char* bytes = (char*)&unint;
If you really do want to make an array (and therefore make a copy of the last 3 bytes, not leave them in place) you do
unsigned char bytes[3]; // or char, but unsigned char is better
bytes[0] = unint >> 16 & 0xFF;
bytes[1] = unint >> 8 & 0xFF;
bytes[2] = unint & 0xFF;
You can do using it the bitwise right shift operator:
array[0] = unint;
array[1] = unint >> 8;
array[2] = unint >> 16;
The least signifcant byte of uint is stored in the first element of the array.
Depending on your needs, you may prefer an union:
typedef union {
unsigned int unint;
unsigned char array[3];
} byteAndInt;
or bit-shift operations:
for(int i=0; i<3; i++)
array[i] = (unint>>8*i) & 0xFF;
The former is not endian-safe.
If by last three, you mean lsb+1, lsb+2 and msb (in other words every byte other than the lsb), then you can use this.
unsigned int unint = some value;
unsigned char * array = ( (unsigned char*)&some_value ) + 1;
Hi I have a base 10 number for example 3198, and the hex representation is 0x0C7E
How do I convert that number to hex and put that hex value in a byte array in the format of [00][0C][7E], assuming the biggest hex value i can have is 0xffffff.
Maybe this will work ?
uint32_t x = 0x0C7E;
uint8_t bytes[3];
bytes[0] = (x >> 0) & 0xFF;
bytes[1] = (x >> 8) & 0xFF;
bytes[2] = (x >> 16) & 0xFF;
/* Go back. */
x = (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0] << 0);
Number is already a continuous memory block - no need to convert it to yet ANOTHER array ! Just fetch separate bytes by using pointer arithmetic:
EDIT: Edited to be endianness-independent
#define FAST_ABS(x) ((x ^ (x>>31)) - (x>>31))
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
uint32_t num = 0xAABBCCDD;
uint32_t N = is_big_endian() * 3;
printf("first byte 0x%02X\n"
"second byte 0x%02X\n"
"third byte 0x%02X\n"
"fourth byte 0x%02X\n",
((unsigned char *) &num)[FAST_ABS(3 - N)],
((unsigned char *) &num)[FAST_ABS(2 - N)],
((unsigned char *) &num)[FAST_ABS(1 - N)],
((unsigned char *) &num)[FAST_ABS(0 - N)]
);
#include <stdio.h>
union uint32_value {
unsigned int value;
struct little_endian {
unsigned char fou;
unsigned char thi;
unsigned char sec;
unsigned char fir;
} le;
struct big_endian {
unsigned char fir;
unsigned char sec;
unsigned char thi;
unsigned char fou;
} be;
};
int main(void)
{
union uint32_value foo;
foo.value = 3198;
printf("%02x %02x %02x %02x\n", foo.le.fir, foo.le.sec, foo.le.thi, foo.le.fou);
return 0;
}
I'm trying to implement this RFC
4.1. Integer
An XDR signed integer is a 32-bit datum that encodes an integer in
the range [-2147483648,2147483647]. The integer is represented in
two's complement notation. The most and least significant bytes are
0 and 3, respectively. Integers are declared as follows:
int identifier;
(MSB) (LSB)
+-------+-------+-------+-------+
|byte 0 |byte 1 |byte 2 |byte 3 | INTEGER
+-------+-------+-------+-------+
<------------32 bits------------>
and here's my code I need to know if there is a better way to do that ?
void packInteger(char *buf,long int i)
{
if(i>=0) {
*buf++ = i>>24;
*buf++ = i>>16;
*buf++ = i>>8;
*buf++ = i;
}
if(i<0) {
i = i*-1;
i = 1 + (unsigned int)(0xffffffffu - i);
buf[0] = (unsigned int)i>>24;
buf[1] = (unsigned int)i>>16;
buf[2] = (unsigned int)i>>8;
buf[3] = (unsigned int)i;
}
}
long int unpackInteger(char *buf)
{
unsigned long int i2 = ((unsigned long int)buf[0]<<24) |
((unsigned long int)buf[1]<<16) |
((unsigned long int)buf[2]<<8) |
buf[3];
long int i;
// change unsigned numbers to signed
if (i2 <= 0x7fffffffu) { i = i2; }
else { i = -1 - (long int)(0xffffffffu - i2); }
return i;
}
int main(void)
{
char buf[4];
packInteger(buf,-31);
printf("%u %u %u %u\n",buf[0],buf[1],buf[2],buf[3]);
long int n = unpackInteger(buf);
printf("%ld",n);
return 0;
}
if someone on 64 bit system is it working or noT ?
version 2
void packInteger(unsigned char *buf,long int i)
{
unsigned long int j = i; // this will convert to 2's complement
*buf++ = i>>24;
*buf++ = i>>16;
*buf++ = i>>8;
*buf++ = i;
}
You should be using unsigned char for your buffers.
A cast to unsigned in C performs the mathematical equivalent of a conversion to 2s complement, so your pack function can be simplified:
void packInteger(unsigned char *buf, long int i)
{
unsigned long u = i;
buf[0] = (u >> 24) & 0xffUL;
buf[1] = (u >> 16) & 0xffUL;
buf[2] = (u >> 8) & 0xffUL;
buf[3] = u & 0xffUL;
}
Your unpack function seems fine (with the change to unsigned char).