473,394 Members | 1,752 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,394 software developers and data experts.

Convert binary char array to integer with reordering

Hi all,

I have a 4 byte char array with the binary data for two 16-bit signed
integers in it like this:

Index 3 2 1 0
Data Bh Bl Ah Al

Where Bh is the high byte of signed 16-bit integer B and so on.

I want to create 32-bit integers A and B with the data in the char
array.

I have tried things like (and various other permutations):

A = (data[1] << 8) | (unsigned int)data[0];
B = (data[3] << 8) | (unsigned int)data[2];

and this works except for when say data[1] = 0x00 and data[0] = 0x80.
In this case, Al gets sign extended all the way to the top of A giving
0xffffff80 which is wrong of course.

I read about the arithmetic converions and I believe it is these that
are converting the right operand to signed and causing the sign
extension.

At the moment, I am getting things right like this:

int A;
int B;
char buildA[4], buildB[4], data[4];

// data[] gets filled here

buildA[0] = data[0];
buildA[1] = data[1];

if (data[1] >> 7)
{
buildA[2] = (char)0xff;
buildA[3] = (char)0xff;
}
else
{
buildA[2] = 0x00;
buildA[3] = 0x00;
}

buildB[0] = data[2];
buildB[1] = data[3];

if (data[3] >> 7)
{
buildB[2] = (char)0xff;
buildB[3] = (char)0xff;
}
else
{
buildB[2] = 0x00;
buildB[3] = 0x00;
}

A = *((int*)buildA);
B = *((int*)buildB);

Surely there is a cleaner way?

Many thanks for your time,

Dave

Nov 15 '05 #1
16 10064
In article <11*********************@g44g2000cwa.googlegroups. com>,
Dave <do********@yahoo.co.uk> wrote:
Hi all,

I have a 4 byte char array with the binary data for two 16-bit signed
integers in it like this:

Index 3 2 1 0
Data Bh Bl Ah Al

Where Bh is the high byte of signed 16-bit integer B and so on.


Not portable. Can't discuss it here. Blah, blah, blah.

Nov 15 '05 #2
If you convert a signed char to an unsigned int, the result is
sign-extended, because the char is signed. Try:
A = (data[1] << 8) | (unsigned char)data[0];
B = (data[3] << 8) | (unsigned achr)data[2];
(Or make the array of type unsigned char)

Now, the unsigned char is default promoted to signed int, and the signed int
should have the same value as the unsigned char...

DickB

"Dave" <do********@yahoo.co.uk> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
Hi all,

I have a 4 byte char array with the binary data for two 16-bit signed
integers in it like this:

Index 3 2 1 0
Data Bh Bl Ah Al

Where Bh is the high byte of signed 16-bit integer B and so on.

I want to create 32-bit integers A and B with the data in the char
array.

I have tried things like (and various other permutations):

A = (data[1] << 8) | (unsigned int)data[0];
B = (data[3] << 8) | (unsigned int)data[2];

and this works except for when say data[1] = 0x00 and data[0] = 0x80.
In this case, Al gets sign extended all the way to the top of A giving
0xffffff80 which is wrong of course.

I read about the arithmetic converions and I believe it is these that
are converting the right operand to signed and causing the sign
extension.

At the moment, I am getting things right like this:

int A;
int B;
char buildA[4], buildB[4], data[4];

// data[] gets filled here

buildA[0] = data[0];
buildA[1] = data[1];

if (data[1] >> 7)
{
buildA[2] = (char)0xff;
buildA[3] = (char)0xff;
}
else
{
buildA[2] = 0x00;
buildA[3] = 0x00;
}

buildB[0] = data[2];
buildB[1] = data[3];

if (data[3] >> 7)
{
buildB[2] = (char)0xff;
buildB[3] = (char)0xff;
}
else
{
buildB[2] = 0x00;
buildB[3] = 0x00;
}

A = *((int*)buildA);
B = *((int*)buildB);

Surely there is a cleaner way?

Many thanks for your time,

Dave

Nov 15 '05 #3
On 2005-10-25, Kenny McCormack <ga*****@yin.interaccess.com> wrote:
In article <11*********************@g44g2000cwa.googlegroups. com>,
Dave <do********@yahoo.co.uk> wrote:
Hi all,

I have a 4 byte char array with the binary data for two 16-bit signed
integers in it like this:

Index 3 2 1 0
Data Bh Bl Ah Al

Where Bh is the high byte of signed 16-bit integer B and so on.


Not portable. Can't discuss it here. Blah, blah, blah.


says who?

int16_t A = data[1]<<8+data[0];
int16_t B = data[3]<<8+data[2];

looks portable to me. chars have to be at least 8 bits [to represent values
from -127 to 127 signed, 0 to 255 unsigned, they have to be], and int16_t where
present is exactly 16 bits and signed. Now ideally you should be using unsigned
char for this, but I don't think it actually matters in this case [well, I
suppose negative zero could still be a trap representation on non twos
complement systems].

Now, the precise _meaning_ of those bytes with regards to the integer value you
end up with may differ in that negative numbers [in this case, where high bit
of byte 1 or 3 is set] can be represented in precisely three different ways
according to the standard, but assuming that he got the byte values in a
portable way in the first place and is using them on the same machine where he
generated them, he can put them back the same way he got them out, and assuming
he used a type guaranteed to be exactly 16 bits (say, c99 int16_t, <stdint.h>)
he loses no information in doing so.

While this exercise may seem pointless, it could be intended as a method of
serialization [in which case, though, he may wish to guarantee a particular
signed representation of his values as well as a byte order]

I can't imagine what (other than the possibility that char may be signed) is
non-portable about this? Was it the use of names that resemble (but aren't
actually the same as) x86 registers that made you think "non-portable!"?

--
How's that for my first post?
Nov 15 '05 #4
Hi Dick,

I used the code you quoted above (left data as char) and it worked
perfectly.

I think data needs to stay char so that the sign extension does happen
with data[1] and [3] as required.

Many thanks,

Dave

Nov 15 '05 #5
Jordan Abel <jm****@purdue.edu> wrote:
On 2005-10-25, Kenny McCormack <ga*****@yin.interaccess.com> wrote:
Not portable. Can't discuss it here. Blah, blah, blah.


says who?


Says a loser with a chip on his shoulder who still hasn't got over being
told, once, that he himself posted something off-topic. Just ignore him
when he's in this mode.

Richard
Nov 15 '05 #6
"Dave" <do********@yahoo.co.uk> wrote:
I want to create 32-bit integers A and B with the data in the char
array.

I have tried things like (and various other permutations):

A = (data[1] << 8) | (unsigned int)data[0];
B = (data[3] << 8) | (unsigned int)data[2];

and this works except for when say data[1] = 0x00 and data[0] = 0x80.
In this case, Al gets sign extended all the way to the top of A giving
0xffffff80 which is wrong of course. char buildA[4], buildB[4], data[4];


An alternative to the other solutions, perhaps safer because you have
less chance of running into signed integer overflow, is to make data
(and because of this, also buildA and buildB) arrays of unsigned int
instead. They won't get sign-extended then simply because they won't
have any sign.
Note also that, since A and B are signed ints, you do not know for
certain that they are 32 bits - use long or int32_t (or even
int_least32_t, which is guaranteed to exist under C99) to get around
this. What's worse, if you ever get an array that represents a value
that doesn't fit in 31 bits - that is, 32 minus the sign bit - you cause
undefined behaviour. Again, an unsigned type (uint_least32_t?) could be
a good solution.

Richard
Nov 15 '05 #7
In article <sl********************@random.yi.org>,
Jordan Abel <jm****@purdue.edu> wrote:
int16_t A = data[1]<<8+data[0];
int16_t B = data[3]<<8+data[2]; looks portable to me.


int16_t does not exist in C89, and in C99 it is optional.
It simply doesn't exist on C99 systems that have (say) 18 bit ints.
That makes it standardized but not portable.

--
Chocolate is "more than a food but less than a drug" -- RJ Huxtable
Nov 15 '05 #8
In article <dj**********@canopus.cc.umanitoba.ca>,
Walter Roberson <ro******@ibd.nrc-cnrc.gc.ca> wrote:
In article <sl********************@random.yi.org>,
Jordan Abel <jm****@purdue.edu> wrote:
int16_t A = data[1]<<8+data[0];
int16_t B = data[3]<<8+data[2];

looks portable to me.


int16_t does not exist in C89, and in C99 it is optional.
It simply doesn't exist on C99 systems that have (say) 18 bit ints.
That makes it standardized but not portable.


Exactly.

Nov 15 '05 #9
Dick de Boer wrote:
If you convert a signed char to an unsigned int, the result is
sign-extended, because the char is signed. Try: A = (data[1] << 8) |
(unsigned char)data[0]; B = (data[3] << 8) | (unsigned achr)data[2];
(Or make the array of type unsigned char)

Now, the unsigned char is default promoted to signed int, and the
signed int should have the same value as the unsigned char...

DickB

"Dave" <do********@yahoo.co.uk> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
Hi all,


Please don't top-post. Your replies belong following or (preferably)
interspersed with properly trimmed quotes.

Brian

Nov 15 '05 #10
On 2005-10-25, Kenny McCormack <ga*****@yin.interaccess.com> wrote:
In article <dj**********@canopus.cc.umanitoba.ca>,
Walter Roberson <ro******@ibd.nrc-cnrc.gc.ca> wrote:
In article <sl********************@random.yi.org>,
Jordan Abel <jm****@purdue.edu> wrote:
int16_t A = data[1]<<8+data[0];
int16_t B = data[3]<<8+data[2];

looks portable to me.


int16_t does not exist in C89, and in C99 it is optional.
It simply doesn't exist on C99 systems that have (say) 18 bit ints.
That makes it standardized but not portable.


Exactly.


which i call "portable enough" - guaranteed not to appear to work on systems
where it won't work.

but, if you must, here's the ruthlessly portable version:

assumptions: unsigned char data[2] contains the high 8 bits and then the low 8
bits of a signed 16-bit integer with the same sign representation as the host,
regardless of the actual byte size or integer width of the host.

int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit in the
* right place, and properly extend it on 2s-comp or 1s-comp systems. */
;

There may be superfluous parentheses - I never could remember the order of
shifting vs bitwise and, and i'm irrationally uncomfortable with the cast
operator

on a signed-magnitude 36-bit system with nine-bit bytes, this should convert
the bytes: 010011010 011001001

to the value
100000000000000000000001101011001001

or -6857 decimal.

I didn't bother with systems with a char of less than 8 bits since that's not
allowed by the standard.
Nov 15 '05 #11
On 2005-10-25, Jordan Abel <jm****@purdue.edu> wrote:
int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit in the
* right place, and properly extend it on 2s-comp or 1s-comp systems. */ /* oops - forgot */
| (~0<-1?(data[1]&0200U)?(~0)<<15:0:0)
/* can anyone guess what that one does? */ ;

Nov 15 '05 #12
On 2005-10-25, Jordan Abel <jm****@purdue.edu> wrote:
int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit in the
* right place, and properly extend it on 2s-comp or 1s-comp systems. */ /* oops - forgot */
| (~0>=-1?(data[1]&0200U)?(~0)<<15:0:0)
/* can anyone guess what that one does? */ ;

Nov 15 '05 #13
Jordan Abel said:
On 2005-10-25, Jordan Abel <jm****@purdue.edu> wrote:
int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit
in the
* right place, and properly extend it on 2s-comp or 1s-comp systems.
*/

/* oops - forgot */
| (~0>=-1?(data[1]&0200U)?(~0)<<15:0:0)
/* can anyone guess what that one does? */
;


Gives a possible trap representation on ones' comp systems? :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/2005
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Nov 15 '05 #14
In article <dj**********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com>,
Richard Heathfield <in*****@invalid.invalid> wrote:
Jordan Abel said:
On 2005-10-25, Jordan Abel <jm****@purdue.edu> wrote:
int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit
in the
* right place, and properly extend it on 2s-comp or 1s-comp systems.
*/

/* oops - forgot */
| (~0>=-1?(data[1]&0200U)?(~0)<<15:0:0)
/* can anyone guess what that one does? */
;


Gives a possible trap representation on ones' comp systems? :-)


Exactly.

Nov 15 '05 #15
On 2005-10-25, Richard Heathfield <in*****@invalid.invalid> wrote:
Jordan Abel said:
On 2005-10-25, Jordan Abel <jm****@purdue.edu> wrote:
int x =
((data[1] & 0177U) << 8) /* non-sign-bit portion of high 'byte' */
| data[0] /* low 'byte' */
| ((~0U<<15)&((int)(signed char)( (data[1] & 0200U) << (CHAR_BIT-8) ))
/* that monster uses the system's sign extension to put the sign bit
in the
* right place, and properly extend it on 2s-comp or 1s-comp systems.
*/

/* oops - forgot */
| (~0>=-1?(data[1]&0200U)?(~0)<<15:0:0)
/* can anyone guess what that one does? */
;


Gives a possible trap representation on ones' comp systems? :-)


~1>=-2, as i just _told_ you on ##c that i'd modify that to if challenged on
this basis ;)
Nov 15 '05 #16

"Default User" <de***********@yahoo.com> wrote in message
news:3s************@individual.net...
Dick de Boer wrote:

<cut top-post.

Please don't top-post. Your replies belong following or (preferably)
interspersed with properly trimmed quotes.

Sorry, slip of my finger (mind)

Dick
Nov 15 '05 #17

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

Similar topics

4
by: David Lawson | last post by:
I know how to conver a string to an array of strings, but I need to convert an ascii string to an array of integers (really unsigned chars). Eg, $str ="ABC"; needs to convert to something...
5
by: rob | last post by:
hey every1, I've got alot of data to write out to file and it's all just 1's and 0's. It's all stored in 2 dimensional arrays of width 32 and varying height. At the moment it's all just...
19
by: jeff | last post by:
how do you convert form byte to Int32 while retaining the binary value of the byte array
7
by: Golan | last post by:
Hi, I need to convert a Binary value to Decimal. I've been told that the value is an unsigned one. How can I do this? I use memcpy into an unsigned char variable, but when I print the value I got...
4
by: msosno01 | last post by:
I have Java client that connects to C++ server. The client sends integer in binary using DataOutputStream write function. I am reading these data into buffer. I have to convert this buffer back...
1
by: willakawill | last post by:
I have a very large binary file saved from a vb array with 2 dimensions; Dim arMatrix() As Byte Dim fNum As Integer ReDim arMatrix(7166, 17769) 'code here to store data from a database into...
7
by: elliotng.ee | last post by:
I have a text file that contains a header 32-bit binary. For example, the text file could be: %%This is the input text %%test.txt Date: Tue Dec 26 14:03:35 2006...
3
by: nguser3552 | last post by:
Hello Everyone, I have a problem I can't surmount, anything is gravy at this point. I need to be able to read any type of file .ext (mov,mpeg,mp3,etc) in binary format. I can do this in C, but ...
9
by: loudking | last post by:
Dear all, I am writing a client-server application and the client should upload a file to the server, then the server should display the content of the file in stdout. Because I have to deal...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.