Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Joining 2 char to 1 short

Reply
Thread Tools

Joining 2 char to 1 short

 
 
Steffen Loringer
Guest
Posts: n/a
 
      06-30-2006
Hi,

I'm using the following function to join 2 char (byte) into one short on
a 32 bit X86 platform:

unsigned short joinUnsigShort(unsigned char a,unsigned char b)
{
unsigned short val = 0;
val = a;
val <<= 8;
val |= b;
return val;
}

Will this also work if compiled on a PowerPC? Are there better ways to
do it?

Thanks a lot!

Steve
 
Reply With Quote
 
 
 
 
Richard Bos
Guest
Posts: n/a
 
      06-30-2006
Steffen Loringer <(E-Mail Removed)> wrote:

> I'm using the following function to join 2 char (byte) into one short on
> a 32 bit X86 platform:
>
> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> {
> unsigned short val = 0;
> val = a;
> val <<= 8;
> val |= b;
> return val;
> }
>
> Will this also work if compiled on a PowerPC?


Depends on what you want. Of course, it _does_ assume that CHAR_BIT is 8
and sizeof (short) is at least 2. Both of those are very common; neither
is guaranteed. It is possible to encounter devices where CHAR_BIT is 32,
and sizeof (char) == sizeof (short) == sizeof (int) == 1.

However, since an unsigned short must be able to hold at least 2**16-1,
and therefore be at least 16 bits wide, CHAR_BIT being exactly 8 already
implies sizeof (short) being at least 2. (The implication doesn't hold
other way; for example, a system where sizeof (short) is 2, but CHAR_BIT
is 9 is quite legal. 36-bit word, char is a quarter word, short half of
one.)

OTOH, the assumption that CHAR_BIT is 8 can be removed by the
marvelously exotic expedient of replacing 8 by CHAR_BIT. The assumption
that sizeof (short) >= 2 is harder to get rid of.

> Are there better ways to do it?


Yes; provided you are willing to put a note in the documentation that
the code assumes that sizeof (short) >= 2, your entire function can be
replaced by

unsigned short joinUnsigShort(unsigned char a,unsigned char b)
{
return (a<<CHAR_BIT) + b;
}

Richard
 
Reply With Quote
 
 
 
 
Steffen Loringer
Guest
Posts: n/a
 
      06-30-2006

>> Are there better ways to do it?

>
> Yes; provided you are willing to put a note in the documentation that
> the code assumes that sizeof (short) >= 2, your entire function can be
> replaced by
>
> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> {
> return (a<<CHAR_BIT) + b;
> }
>
> Richard


So I assume bit-shifting in this function is independend concerning
big/low endian systems!? Does the compiler take care for correct
shifting in both cases?

 
Reply With Quote
 
Chris Dollin
Guest
Posts: n/a
 
      06-30-2006
Steffen Loringer wrote:

>>> Are there better ways to do it?

>>
>> Yes; provided you are willing to put a note in the documentation that
>> the code assumes that sizeof (short) >= 2, your entire function can be
>> replaced by
>>
>> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
>> {
>> return (a<<CHAR_BIT) + b;
>> }
>>
>> Richard

>
> So I assume bit-shifting in this function is independend concerning
> big/low endian systems!? Does the compiler take care for correct
> shifting in both cases?


There isn't a bigendian/littleendian issue to worry about here. Why did
you think there was?

--
Chris "seeker" Dollin
"Life is full of mysteries. Consider this one of them." Sinclair, /Babylon 5/

 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      06-30-2006
Steffen Loringer wrote:
>
> >> Are there better ways to do it?

> >
> > Yes; provided you are willing to
> > put a note in the documentation that
> > the code assumes that sizeof (short) >= 2,
> > your entire function can be replaced by
> >
> > unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> > {
> > return (a<<CHAR_BIT) + b;
> > }
> >
> > Richard

>
> So I assume bit-shifting in this function is independend concerning
> big/low endian systems!? Does the compiler take care for correct
> shifting in both cases?


Yes.
The meaning of the code might be more obvious
if done with arithmetic operations.

unsigned short joinUnsigShort(unsigned char a,unsigned char b)
{
return (UCHAR_MAX + 1U) * a + b;
}

That also avoids the undefined behavior associated
with shifting too far, if sizeof(short) is greater than one.
And, (UCHAR_MAX + 1U) * a, is likely to be compiled t
o code which is just as fast as the shifting code.

If sizeof(short) is equal to one, then the function returns b,
so the "sizeof (short) > 1" documentation
that Richard Boss mentioned, still applies.

--
pete
 
Reply With Quote
 
Sven Fülster
Guest
Posts: n/a
 
      06-30-2006

"Steffen Loringer" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)...
>
> >> Are there better ways to do it?

> >
> > Yes; provided you are willing to put a note in the documentation that
> > the code assumes that sizeof (short) >= 2, your entire function can be
> > replaced by
> >
> > unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> > {
> > return (a<<CHAR_BIT) + b;
> > }
> >
> > Richard

>
> So I assume bit-shifting in this function is independend concerning
> big/low endian systems!? Does the compiler take care for correct
> shifting in both cases?
>


<OT>
Have a look at the functions
ntohs() [htons()] which convert a short value from network byte order (big
endian) to host byte order (whatever your host system is) [and vice versa]
</OT>


 
Reply With Quote
 
=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=
Guest
Posts: n/a
 
      06-30-2006
Sven Fülster wrote:
> "Steffen Loringer" <(E-Mail Removed)> schrieb im Newsbeitrag
> news:(E-Mail Removed)...
>>>> Are there better ways to do it?
>>> Yes; provided you are willing to put a note in the documentation that
>>> the code assumes that sizeof (short) >= 2, your entire function can be
>>> replaced by
>>>
>>> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
>>> {
>>> return (a<<CHAR_BIT) + b;
>>> }
>>>
>>> Richard

>> So I assume bit-shifting in this function is independend concerning
>> big/low endian systems!? Does the compiler take care for correct
>> shifting in both cases?
>>

>
> <OT>
> Have a look at the functions
> ntohs() [htons()] which convert a short value from network byte order (big
> endian) to host byte order (whatever your host system is) [and vice versa]
> </OT>


Or get/put them directly in the right order(big endian in this case) ?
uint16_t unpack16(uint8_t buf[2])
{
return buf[0]<<8 | buf[1];
}
void pack16(uint16_t val,uint8_t buf[2])
{
buf[0] = val>>8;
buf[1] = val&0xff;
}
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      06-30-2006
pete wrote:
>
> Steffen Loringer wrote:
> >
> > >> Are there better ways to do it?
> > >
> > > Yes; provided you are willing to
> > > put a note in the documentation that
> > > the code assumes that sizeof (short) >= 2,
> > > your entire function can be replaced by
> > >
> > > unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> > > {
> > > return (a<<CHAR_BIT) + b;
> > > }
> > >
> > > Richard

> >
> > So I assume bit-shifting in this function is independend concerning
> > big/low endian systems!? Does the compiler take care for correct
> > shifting in both cases?

>
> Yes.
> The meaning of the code might be more obvious
> if done with arithmetic operations.
>
> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> {
> return (UCHAR_MAX + 1U) * a + b;
> }
>
> That also avoids the undefined behavior associated
> with shifting too far, if sizeof(short)
> is


should be "isn't"

> greater than one.
> And, (UCHAR_MAX + 1U) * a, is likely to be compiled t
> o code which is just as fast as the shifting code.
>
> If sizeof(short) is equal to one, then the function returns b,
> so the "sizeof (short) > 1" documentation
> that Richard Boss mentioned, still applies.
>
> --
> pete


--
pete
 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      06-30-2006
Steffen Loringer posted:

> Hi,
>
> I'm using the following function to join 2 char (byte) into one short

on
> a 32 bit X86 platform:
>
> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> {
> unsigned short val = 0;
> val = a;



Ridculously inefficient.

Why set a variable's value to zero, and the immediately give it another
value?


> val <<= 8;



val <<= CHAR_BIT; /* A byte isn't always 8 bits */


> val |= b;
> return val;
> }
>
> Will this also work if compiled on a PowerPC? Are there better ways to
> do it?



Not necessarily. If unsigned char has 16 value bits and so does short,
then you won't get the result you want.



--

Frederick Gotham
 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      06-30-2006
pete posted:

> Steffen Loringer wrote:
>>
>> >> Are there better ways to do it?
>> >
>> > Yes; provided you are willing to
>> > put a note in the documentation that
>> > the code assumes that sizeof (short) >= 2,
>> > your entire function can be replaced by
>> >
>> > unsigned short joinUnsigShort(unsigned char a,unsigned char b)
>> > {
>> > return (a<<CHAR_BIT) + b;
>> > }
>> >
>> > Richard

>>
>> So I assume bit-shifting in this function is independend concerning
>> big/low endian systems!? Does the compiler take care for correct
>> shifting in both cases?

>
> Yes.
> The meaning of the code might be more obvious
> if done with arithmetic operations.
>
> unsigned short joinUnsigShort(unsigned char a,unsigned char b)
> {
> return (UCHAR_MAX + 1U) * a + b;
> }



If I'm not mistaken, (UCHAR_MAX + 1U) is well within its rights to
evaluate to zero. Imagine the following system:

unsigned char: 32 bits, no padding
unsigned short: 32 bits, no padding
unsigned int: 32 bits, no padding
unsigned long: 32 bits, no padding



--

Frederick Gotham
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Linking error LNK2001 - "__declspec(dllimport) private: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Tidy(unsigned short)" (__imp_?_Tidy@?$basic_string@DU?$char_ sharmadeep1980@gmail.com C++ 1 07-07-2006 07:27 AM
(const char *cp) and (char *p) are consistent type, (const char **cpp) and (char **pp) are not consistent lovecreatesbeauty C Programming 1 05-09-2006 08:01 AM
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM
char + short = char* SinusX C++ 5 05-18-2004 03:40 PM
the difference between char a[6] and char *p=new char[6] . wwj C++ 7 11-05-2003 12:59 AM



Advertisments