Packing bytes into chars

C

Chris

What's the most efficient way to pack two bytes into a char? This is the
best I could come up with, but it looks terrible:

byte b0 = 0;
byte b1 = 1;

char ch = (char)(((int)b0 << 8) | b1);

This appears to have two explicit casts and one implicit one. It's also
really slow.
 
E

Eric Sosman

Chris said:
What's the most efficient way to pack two bytes into a char? This is the
best I could come up with, but it looks terrible:

byte b0 = 0;
byte b1 = 1;

char ch = (char)(((int)b0 << 8) | b1);

This appears to have two explicit casts and one implicit one. It's also
really slow.

Question: Why do you think it's slow? Have you made
measurements?

Observation: Although this will work for the particular
values shown in the example, it will fail rather badly for
bytes whose sign bit is set.
 
R

Roedy Green

char ch = (char)(((int)b0 << 8) | b1);

This appears to have two explicit casts and one implicit one. It's also
really slow.

You can prune out the (int) cast which is implicit. You can prune out
one level of () which are implied by precedence. However the generated
code is the same. That is as tight as I can make it.


char ch = (char)( b0 << 8 | b1 );


Note, this code will only work if the high bit is off on b1
Otherwise you have to write:

char ch = (char)( b0 << 8 | b1 & 0xff );
 
S

Steve Horsley

What's the most efficient way to pack two bytes into a char? This is the
best I could come up with, but it looks terrible:

byte b0 = 0;
byte b1 = 1;

char ch = (char)(((int)b0 << 8) | b1);

This appears to have two explicit casts and one implicit one. It's also
really slow.

Worse, it doesn't work. The implict promotion of b1 to int will cause sign
extension and overwrite b0's value if b1 is negative. Try:

char ch = (char) ( (b0 << 8) | (b1 & 255) );

The sign extension of b0 gets lost again in the cast to int, so that's not an
issue.

Steve
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Chris said:
What's the most efficient way to pack two bytes into a char? This is the
best I could come up with, but it looks terrible:

byte b0 = 0;
byte b1 = 1;

char ch = (char)(((int)b0 << 8) | b1);

This appears to have two explicit casts and one implicit one. It's also
really slow.

Well, this one is slower but it is correct for all byte values:

char pack(byte hi, byte low)
{
int i = hi >> 7 == 0 ? hi : (256 + hi);
int i2 = low >> 7 == 0 ? low : (256 + low) ;

char c = (char)((i << 8) + i2);
return c;
}
 
R

Roedy Green

int i = hi >> 7 == 0 ? hi : (256 + hi);
int i2 = low >> 7 == 0 ? low : (256 + low) ;

you don't need that for the high byte since there is nothing extended
to cause trouble.

you can compute the low byte more quickly with

int i2 = low & 0xff;
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Roedy said:
you don't need that for the high byte since there is nothing extended
to cause trouble.

you can compute the low byte more quickly with

int i2 = low & 0xff;

True, true. I was a slight bit embarassed after reading your solution :)
But anyway, what on earth was the rationale behind making byte signed?
 
R

Roedy Green

But anyway, what on earth was the rationale behind making byte signed?

I think that was goofy too. I want a signed byte perhaps 1% as often
as an unsigned one.

This probably was inherited from C where they could not make up their
mind. It started out signed since chars were 7 bits in the early days
of the PDP-11.
 
S

Steve Horsley

Roedy Green wrote:
But anyway, what on earth was the rationale behind making byte signed?

I still think someone must have put LSD in the coffee machine.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top