conversion...

H

Herwig

unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig
 
D

David Resnick

Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig

memcpy(&i, &c[2], 2);

That said, you have some portability issues to consider

1) endianness (you may have to reverse the bytes), along the lines of
unsigned char *p = i;
p[0] = c[3];
p[1] = c[2];

2) relative size of char and short is assumed to be 1 byte for
char (guaranteed by standard that sizeof(char) == 1), and
2 bytes for short (not guaranteed).

3) Probably some others I'm ignorant of but you'll no doubt hear
of shortly...

-David
 
C

Chris Dollin

Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?

Dunno about the *easiest*; I'd like to have a fighting chance of
being portable, as well.

I'd go for

i = ((unsigned char) c[2] << CHAR_BIT) + (unsigned char) c[3];

What problems didn't I see?
 
W

Walter Roberson

:unsigned short int i;
:char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };

:The 3rd and 4th byte represent the short value "12".
:Q: what is the easiest way to copy these 2 bytes from c to i?

i = (unsigned short) c[2] <<8 || (unsigned short) c[3];
 
W

Walter Roberson

:> unsigned short int i;
:> char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };

:> The 3rd and 4th byte represent the short value "12".
:> Q: what is the easiest way to copy these 2 bytes from c to i?

:Dunno about the *easiest*; I'd like to have a fighting chance of
:being portable, as well.

: i = ((unsigned char) c[2] << CHAR_BIT) + (unsigned char) c[3];

:What problems didn't I see?

If the source is taken to a different platform with a different
CHAR_BIT then with the same literal constants you would get a
different short. The shift value should probably be an application
constant rather than an implimentation constant.
 
D

David Resnick

David said:
Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig


memcpy(&i, &c[2], 2);

That said, you have some portability issues to consider

1) endianness (you may have to reverse the bytes), along the lines of
unsigned char *p = i;
p[0] = c[3];
p[1] = c[2];

2) relative size of char and short is assumed to be 1 byte for
char (guaranteed by standard that sizeof(char) == 1), and
2 bytes for short (not guaranteed).

3) Probably some others I'm ignorant of but you'll no doubt hear
of shortly...

-David

Other's solutions appear much better than mine, calculation avoids
the problems above. I saw the word "copy" and suggested a way to copy,
rather than "use arithmetic".

-David
 
C

Christian Kandeler

Walter said:
:unsigned short int i;
:char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };

:The 3rd and 4th byte represent the short value "12".
:Q: what is the easiest way to copy these 2 bytes from c to i?

i = (unsigned short) c[2] <<8 || (unsigned short) c[3];

I'm pretty sure that one of the '|' characters is superfluous, but I can't
seem to work out which...


Christian
 
C

CBFalconer

Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?

int ix;
char *p

for (p = &c[3], ix = 0, i = 0; ix < 2; ix++)
i = i * 256 + (unsigned char) p[ix];

This is independant of endianess and of the size of a byte,
provided the char array doesn't contain values over 255. The point
is to design around the input format.
 
W

Walter Roberson

:> i = (unsigned short) c[2] <<8 || (unsigned short) c[3];

:I'm pretty sure that one of the '|' characters is superfluous, but I can't
:seem to work out which...

It's the middle one...

[After programming tables of regular expressions for days on end, I'm mostly
surprised that I didn't start the line with '^ ]
 
O

Old Wolf

Christian said:
Walter said:
:unsigned short int i;
:char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };

:The 3rd and 4th byte represent the short value "12".
:Q: what is the easiest way to copy these 2 bytes from c to i?

i = (unsigned short) c[2] <<8 || (unsigned short) c[3];

I'm pretty sure that one of the '|' characters is superfluous, but I can't
seem to work out which...

The code is wrong anyway. For example, if c[3] is -1 then
(unsigned short)c[3] will be 0xFFFF (on a typical system),
which overwrites whatever you got from c[2] .

Then (extra for pedants..) you have the possibility of creating
a trap representation; if int is bigger than short then the type
of each operand of the '|', after the usual promotions,
will be 'signed int'.

Chris Dollin's version was correct.
 
P

pete

Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig

i = c[2] << 8 + c[4];
 
P

pete

CBFalconer said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?

int ix;
char *p

for (p = &c[3], ix = 0, i = 0; ix < 2; ix++)
i = i * 256 + (unsigned char) p[ix];

This is independant of endianess and of the size of a byte,
provided the char array doesn't contain values over 255. The point
is to design around the input format.

The cast converts a char type expression to unsigned char
just prior to be converted to either int or unsigned.
I don't see the point of doing that with the cast.
 
P

pete

pete said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig

i = c[2] << 8 + c[4];

That's assuming that c is an array
initialised with integer constants.
 
P

pete

pete said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?

int ix;
char *p

for (p = &c[3], ix = 0, i = 0; ix < 2; ix++)
i = i * 256 + (unsigned char) p[ix];

This is independant of endianess and of the size of a byte,
provided the char array doesn't contain values over 255. The point
is to design around the input format.

The cast converts a char type expression to unsigned char
just prior to be converted to either int or unsigned.
I don't see the point of doing that with the cast.

I think my problem is that I assumed that c was being
initialised with integer constants within the range of char.
 
C

CBFalconer

pete said:
CBFalconer said:
Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?

int ix;
char *p

for (p = &c[3], ix = 0, i = 0; ix < 2; ix++)
i = i * 256 + (unsigned char) p[ix];

This is independant of endianess and of the size of a byte,
provided the char array doesn't contain values over 255. The
point is to design around the input format.

The cast converts a char type expression to unsigned char
just prior to be converted to either int or unsigned.
I don't see the point of doing that with the cast.

If the native char type is signed, without the cast negative values
will be sign extended on conversion to int and things won't work.

BTW, the index [3] above should be [2].
 
P

Peter Nilsson

Chris said:
Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
.
Dunno about the *easiest*; I'd like to have a fighting chance of
being portable, as well.
.
I'd go for
.
i = ((unsigned char) c[2] << CHAR_BIT)
+ (unsigned char) c[3];
.
What problems didn't I see?

1. Theoretically, sizeof(short) can be 1, therefore left
shifting by CHAR_BIT bits can invoke undefined behaviour.

In such cases, how does one copy _two_ bytes to a single
byte entity?

Whilst a 'robust' replacement for the above is...

i = ((c[2] + 0u) << (CHAR_BIT-1) << 1) + c[3];

....there is another issue...

2. More generally, CHAR_BIT needn't be 8. The question has
to be asked what the OP actually wants to happen! Are they
joining two octet values to form a 16-bit word? If so, then
your code could fail on machines where CHAR_BIT isn't 8.
[But also, the OP's choice of _plain_ char becomes suspect.]
 
P

pete

pete said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig

i = c[2] << 8 + c[4];

c[4] should be c[3],
and assumptions have been made.
 
C

Chris Dollin

Peter said:
Chris said:
Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
.
Dunno about the *easiest*; I'd like to have a fighting chance of
being portable, as well.
.
I'd go for
.
i = ((unsigned char) c[2] << CHAR_BIT)
+ (unsigned char) c[3];
.
What problems didn't I see?

1. Theoretically, sizeof(short) can be 1, therefore left
shifting by CHAR_BIT bits can invoke undefined behaviour.

In such cases, how does one copy _two_ bytes to a single
byte entity?

I think we have to assume that shorts are twice as long as chars.
If not, it's not clear the problem is soluble ...
Whilst a 'robust' replacement for the above is...

i = ((c[2] + 0u) << (CHAR_BIT-1) << 1) + c[3];

...there is another issue...

2. More generally, CHAR_BIT needn't be 8. The question has
to be asked what the OP actually wants to happen! Are they
joining two octet values to form a 16-bit word? If so, then
your code could fail on machines where CHAR_BIT isn't 8.
[But also, the OP's choice of _plain_ char becomes suspect.]

I picked CHAR_BIT precisely because it might not be 8. But I
think we need stronger guards, because the code relies on short
being *at least* twice as long as char.

I'm now contemplating the possibility of a machine with 9-bit
chars and 16-bit shorts.
 
J

Jarno A Wuolijoki

pete said:
Herwig said:
unsigned short int i;
char c[] = { 0x00, 0x04, 0x00, 0x0C, 'A', 'B', 'C', 0x00 };
^^^^^^^^^^^
The 3rd and 4th byte represent the short value "12".
Q: what is the easiest way to copy these 2 bytes from c to i?
Herwig

i = c[2] << 8 + c[4];

c[4] should be c[3],
and assumptions have been made.

Is any of the assumptions that int has more than 20 bits? ;)
 

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
474,161
Messages
2,570,891
Members
47,423
Latest member
henerygril

Latest Threads

Top