I need to copy the data from 2 char
(8 bit long) to a single short
(16 bit long). I tried two different ways, but can't get it to work.
void char2short(char* pchar, short* pshort)
{
memcpy(pshort , pchar + 1 , 1);
memcpy(pshort + 1, pchar , 1);
}
And the other one:
void char2short(char* pchar, short* pshort)
{
short aux;
aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8);
*pshort = aux;
}
#include <stdio.h>
void char2short(unsigned char* pchar, unsigned short* pshort)
{
*pshort = (pchar[0] << 8) | pchar[1];
}
int main()
{
unsigned char test[2];
unsigned short result = 0;
test[0] = 0xAB;
test[1] = 0xCD;
char2short(test, &result);
printf("%#X\n",result);
return 0;
}
this will do the job.
Assuming pchar
is an array that contains your 2 chars, how about:
*pshort = (uint16_t)(((unsigned int)pchar[0]) |
(((unsigned int)pchar[1])<<8));
P.S. This work for little endianess.
Others didn't explain why your code didn't work, so I'll take a quick stab at it:
memcpy(pshort , pchar + 1 , 1);
memcpy(pshort + 1, pchar , 1);
Adding to a pointer TYPE * p
moves the pointer by increments of sizeof( TYPE )
(so it does point at the next element, remember this is only defined if inside an array). So while pchar + 1
is correct, pshort + 1
is not (as it's addressing the next short
).
aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8);
Errr.... the right hand side is broken in more ways than one. First, *(pchar+1)
is a char
, and & 0xFF00
on a char
will always yield 0 (because a char
is only 8 bits to begin with, at least on contemporary machines...). And then you shift that 8 bits to the right...?
And just in case you weren't aware of it, if you hadn't used 0x00FF on the left hand side (promoting *pchar
to the width of the right-hand operand) but (char
-sized) 0xFF, the result of that operation would still be of type char
, and shifting that 8 bits to the left doesn't make much sense either (as the type doesn't get expanded magically).
Another way to go about this not mentioned yet is the union
:
#include <stdio.h>
struct chars_t
{
// could also go for char[2] here,
// whichever makes more sense semantically...
char first;
char second;
};
union combo_t
{
// elements of a union share the memory, i.e.
// reside at the same address, not consecutive ones
short shrt;
struct chars_t chrs;
};
int main()
{
union combo_t x;
x.chrs.first = 0x01;
x.chrs.second = 0x02;
printf( "%x", x.shrt );
return 0;
}
If you're using this in a larger context, beware of struct padding.
When doing bitwise operations, use robust code with real fixed-size integers, of known signedness. This will prevent you from writing bugs related to implicit type conversions, causing unintended signedness. The char
type is particularly dangerous, since it has implementation-defined signedness. It should never be used for storing numbers.
#include <stdint.h>
void char2short(const uint8_t* pchar, uint16_t* pshort)
{
*pshort = ((uint16_t)pchar[0] << 8) | (uint16_t)pchar[1];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With