473,385 Members | 2,044 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Joining 2 char to 1 short

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
Jun 30 '06 #1
15 8166
Steffen Loringer <st**************@freenet.de> 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
Jun 30 '06 #2
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?

Jun 30 '06 #3
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/

Jun 30 '06 #4
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
Jun 30 '06 #5

"Steffen Loringer" <st**************@freenet.de> schrieb im Newsbeitrag
news:4g*************@news.dfncis.de...
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>
Jun 30 '06 #6
Sven Fülster wrote:
"Steffen Loringer" <st**************@freenet.de> schrieb im Newsbeitrag
news:4g*************@news.dfncis.de...
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;
}
Jun 30 '06 #7
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
Jun 30 '06 #8
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
Jun 30 '06 #9
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
Jun 30 '06 #10
Frederick Gotham wrote:
unsigned short val = 0;
val = a;


Ridculously inefficient.

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


It's poorly written not inefficient. I suggest you look at the output
of an optimizing compiler from time to time :-)
val <<= 8;

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


Um, what if you want to pack 8 bit words into a larger word? For [say]
network coding you want to be explicit.
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.


Which is why he shifted by 8 and not CHAR_BIT. Chances are the inputs
are ranged limited to 0..255.

Speaking as someone who writes code on an x86 and has it excuted on all
manners of MIPS, PPC, SPARC, IA64 and others I think I know what I'm
talking about here.

If the intent was to pack two 8 bit values into a single integer the
routine

unsigned pack(unsigned char a, unsigned char b) { return (a<<8)|b; }

Will work fine.

Of course in my code I use macros for all this and I explicitly cast
everything to char or long [unsigned of course] just to cover my bases.

Tom

Jun 30 '06 #11
Frederick Gotham wrote:

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.


Yes.

The part of my post which you snipped, addresses that issue:

"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
Jun 30 '06 #12
Tom St Denis posted:
Speaking as someone who writes code on an x86 and has it excuted on all
manners of MIPS, PPC, SPARC, IA64 and others I think I know what I'm
talking about here.

That shouldn't be an issue if you're writing portable code.

By the way, was the injection of arrogance intentional?
unsigned pack(unsigned char a, unsigned char b) { return (a<<8)|b; }

Will work fine.

I'd probably do something like:

#include <assert.h>

unsigned short Pack( unsigned char a, unsigned char b )
{
assert( a <= 255 );
assert( b <= 255 );

return ( a << 8 ) | b;
}
--

Frederick Gotham
Jun 30 '06 #13
Steffen Loringer <st**************@freenet.de> writes:
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?


It will do what it says. Whether it will do what you want depends on
exactly what you want, which you haven't quite told us.

There are many possible ways to join two chars into a short. What
exactly are you trying to accomplish? Do you want the value of "a" in
the high-order bits of the result? Do you want it in the leftmost
(lowest address) portion of the result?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 30 '06 #14
"Sven Fülster" <sv***********@materna.dewrote:
"Steffen Loringer" <st**************@freenet.deschrieb im Newsbeitrag
news:4g*************@news.dfncis.de...
>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;
}
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 shift operators work on values, not on representations. This
code always puts a in the higher-value byte of the return value, and b
in the lower-value one.
<OT>
Have a look at the functions ntohs() [htons()]
Or rather, don't. Not only will they make your code less portable, they
will not add any functionality in this case.

Richard
Jul 3 '06 #15
On Fri, 30 Jun 2006 11:18:17 GMT, pete <pf*****@mindspring.comwrote:
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;
To be picky, at least ( (unsigned short)a << CHAR_BIT ) + b
or (as I prefer) to either use both bitwise
(unsigned short)a << CHAR_BIT | b /* precedence ok */
or both arithmetic as you do below.

Otherwise unsigned char of 8 or even 9 or 12 bits can promote to
signed int of as little as 15+1 bits, in which left shift of some
uchar values by CHAR_BIT overflows and produces U.B.

<snip>
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.
Corrected to isn't. But size or even width of short doesn't matter. It
is U.B. if unsigned int is the same width as unsigned char (so the
promoted value is being shifted by >= its width) OR if (signed) int is
wider than char but not 'more than twice' (precisely, does not have at
least twice as many value/magnitude bits, plus sign).
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.

- David.Thompson1 at worldnet.att.net
Jul 10 '06 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Danny Anderson | last post by:
Hola! I have an array of shorts that represents a stream of data. This data is packed in tight, so certain elements may actually contain data for more than one variable. I am to decipher this...
18
by: Charles Kerekes | last post by:
Hello everyone, I am still learning C++, so I'm not sure what I'm trying to do is possible. Her is a simplified example: char Test = 'L'; cout << "Test Char as decimal: " << dec << Test <<...
2
by: Chris | last post by:
Hi, I seem to be having a problem I can't quite figure out. Currently, I have the following code (below). In the SendMsg function, I create a 'Qtkmsg' which converts the string 'text' into a...
1
by: Stephen Richardson | last post by:
I have a C++ dll which returns a structure, the structure contains a char variable, as shown below. struct MyCStruct { short iNumber; char Name; }; I've declared a structure in C# as shown...
0
by: arnuld | last post by:
this programme runs without any trouble. it took 45 minutes of typing. i posted it here so that people can save their precious time: // Stroustrup special edition // chapter 4 exercise 2 //...
2
by: sam.barker0 | last post by:
Hi guys, I am trying to form an IPV6 address string from the address bytes contained in a unsigned char buffer char tempstring; sprintf(tempstring, "%x:%x:%x:%x:%x:%x:%x:%x",htons(*((unsigned...
17
by: spasmous | last post by:
I need a way to search through a block of memory for a char array "DA" using a pointer to a short. Ideally I would like to write something like: short *data = ... some data...; int j = 0;...
20
by: =?Utf-8?B?ZW1pdG9qbGV5ZXM=?= | last post by:
Hi everyone: i read from the documentation of a dll that there is a struct that uses char for storing an IP address. How can it be? and how come i can get to representate the same value in a...
5
by: Neel | last post by:
Hi friends, How can I store a short into an unsigned char??? its like unsigned char msg; //now I want to assign 0xAB into it.
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.