473,406 Members | 2,217 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,406 software developers and data experts.

convert a char[4] (binary) to an unsigned long

Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent

Aug 5 '05 #1
19 16754
Vincent sade:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent


assert(sizeof(long) == 4);
char b[4] = {0x01,0x02,0x03,0x04};
unsigned long a = 0;
a |= (b[0] << 24);
a |= (b[1] << 16);
a |= (b[2] << 8);
a |= b[3];

But if you have MSB in b[3] then you should reverse the order.
Beware of big endian and little endian.

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Aug 5 '05 #2
Vincent wrote:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent


I don't think this is possible without knowing the endian-ness of the
machine. Maybe someone will correct me.

If the char[4] came from the machine, then you could probably do a
reinterpret_cast, but I'm almost positive it won't be portable.

// assume this has your binary unsigned long
extern char ul_bin[4];
unsigned long ul = *reinterpret_cast<unsigned long *>(ul_bin);

--John Ratliff
Aug 5 '05 #3
The program will have to work on MS Windows 2000. The char[4] is a set
of characters, read from a file.

I hope this will help you answering my question.

Aug 5 '05 #4

Vincent skrev:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent


Use memcpy:

unsigned long ChararrToLong(const char * const src)
{
unsigned long dest;
memcpy(&dest, src, sizeof(dest));
return dest;
}
This may be what you want or not. If you depend on the chars being put
in a specific order into the unsigned long, you might want to do some
byte-swapping while copying.

Aug 5 '05 #5
Vincent sade:
The program will have to work on MS Windows 2000. The char[4] is a set
of characters, read from a file.

I hope this will help you answering my question.


Find out what format the long's are stored in, what endianness.

long l = 0x04030201

can be stored as

Big endian: 0x04030201
Little endian: 0x01020304

Or any random order you desire in your file, but if you don't
know the byte order, how will you be able to read them back correctly?

http://en.wikipedia.org/wiki/Endianess

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Aug 5 '05 #6
Vincent wrote:
The program will have to work on MS Windows 2000. The char[4] is a set
of characters, read from a file.

I hope this will help you answering my question.


It will only work if the char[4] read from Windows was created on a
machine with endian-ness the same as Windows 2000 (little endian for
x86) written in endian correct order.

In other words, if you wrote an unsigned long created on a machine to a
file, and then wanted to read that unsigned long from a char[4] byte
array on the same machine, the reinterpret_cast would work. If this file
is created on some other machine, you can only know if it would work if
you know the endian-ness of the machine which created the file.

A question though, why are you reading an unsigned long into a char[4]
array anyways? Why not read it directly into an unsigned long? Or, how
does the unsigned long get written in the first place? Maybe you should
consider writing it as a string instead and parsing the string back
using strtoul() instead.

--John Ratliff
Aug 5 '05 #7
On Fri, 05 Aug 2005 12:25:38 +0200, Tobias Blomkvist <vo**@void.void>
wrote in comp.lang.c++:
Vincent sade:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent

assert(sizeof(long) == 4);


This doesn't actually solve the problem. And what happens if
sizeof(long) is 8, which it is on some 64 bit platforms?
char b[4] = {0x01,0x02,0x03,0x04};
unsigned long a = 0;
a |= (b[0] << 24);
The problem here is that b[0] is promoted to either int or unsigned
int before it is shifted. There are still a large number of platforms
where long has 32 bits but int has only 16. Shifting by 24 on such a
platform is undefined behavior, and will almost certainly give the
wrong results.

Perhaps you think that the extra step of initializing 'a' to 0 and
using |= forces b[0] to be promoted to unsigned long. It most
certainly does not. b[0] is promoted to either int or unsigned int,
the shift is performed and assuming there is no undefined behavior or
the program continues regardless, the resulting unsigned int value is
only then promoted to unsigned long.

Should be:

unsigned long a = ((unsigned long)b1 << 24);
a |= (b[1] << 16);
Same cast here.
a |= (b[2] << 8);
a |= b[3];
The last two do not need the cast. Except maybe platforms where
unsigned char and int both have 16 bits, and the value in the unsigned
char is greater than 255. And yes, there are platforms like this that
actually have C++ compilers.
But if you have MSB in b[3] then you should reverse the order.
Beware of big endian and little endian.

Tobias


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 6 '05 #8
John Ratliff wrote:
I don't think this is possible without knowing the endian-ness of the
machine. Maybe someone will correct me.


int x = 1;

endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;

Some compilers (GCC for sure) can optimize away code using this expression.

e.g.

int x = 1;
if ( * (char *) & x )
{
... little endian code ...
... optimized away when compiled for a little endian machine ...
} else
{
... big endian code ...
... optimized away when compiled for a big endian machine ...
}
Aug 6 '05 #9
Vincent wrote:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

See:
http://groups-beta.google.com/group/...6?dmode=source

http://groups.google.com/group/comp....F-8&edition=us
Aug 6 '05 #10
Jack Klein sade:

assert(sizeof(long) == 4);

This doesn't actually solve the problem. And what happens if
sizeof(long) is 8, which it is on some 64 bit platforms?


It fails.
char b[4] = {0x01,0x02,0x03,0x04};
unsigned long a = 0;
a |= (b[0] << 24);

The problem here is that b[0] is promoted to either int or unsigned
int before it is shifted. There are still a large number of platforms
where long has 32 bits but int has only 16. Shifting by 24 on such a
platform is undefined behavior, and will almost certainly give the
wrong results.


True. An
assert(sizeof(int) == 4);
would secure the code.

The last two do not need the cast. Except maybe platforms where
unsigned char and int both have 16 bits, and the value in the unsigned
char is greater than 255. And yes, there are platforms like this that
actually have C++ compilers.


On the other hand, writing code like this, you must be aware. Why do
you think I used assert?

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Aug 6 '05 #11
"Gianni Mariani"
int x = 1;

endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;


Can someone explain how this expression works? std::reverse is useful for
changing endiann type.

Fraser.
Aug 8 '05 #12
"Fraser Ross"
"Gianni Mariani"
int x = 1;

endianness = * (char *) & x ? LITTLE_ENDIAN : BIG_ENDIAN;


Can someone explain how this expression works? std::reverse is useful for
changing endiann type.

Fraser.


I see it now. A static_cast would be more understandable. For a moment I
thought there was a use of a bit-wise operator.

Fraser.
Aug 8 '05 #13

"Fraser Ross"
I see it now. A static_cast would be more understandable.


No, reinterpret_cast is required.

Fraser.
Aug 8 '05 #14
&x points to a number of bytes which contain (on a big endian machine,
LSB is at highest byte address) 0, 0, ... , 1, and (on a little endian
machine, LSB is at lowest byte address) 1, 0, ... 0

Interpreting the pointer as a char * and getting the byte pointed to
will return the contents of the lowest addressed byte of the word,
which will be 0 for big endian machines and 1 for little endian
machines.

Optimising out the code is presumably a result of gcc recognising that
particular pattern - it would be rather dangerous if you were cross
compiling!

Aug 8 '05 #15
Thanks for this suggestion. It works! Somewhere else in my script, I
have to convert an unsigned long to a char[4]. I tried to use memcpy to
create a LongtoChararr function, but i failed. I'm not very familiar
with memcpy. Can you help me again?
Hans wrote:
Vincent skrev:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?

Thanks,
Vincent


Use memcpy:

unsigned long ChararrToLong(const char * const src)
{
unsigned long dest;
memcpy(&dest, src, sizeof(dest));
return dest;
}
This may be what you want or not. If you depend on the chars being put
in a specific order into the unsigned long, you might want to do some
byte-swapping while copying.


Aug 8 '05 #16
Tobias Blomkvist wrote:
Jack Klein sade:

assert(sizeof(long) == 4);


This doesn't actually solve the problem. And what happens if
sizeof(long) is 8, which it is on some 64 bit platforms?


It fails.
char b[4] = {0x01,0x02,0x03,0x04};
unsigned long a = 0;
a |= (b[0] << 24);

The problem here is that b[0] is promoted to either int or unsigned
int before it is shifted. There are still a large number of platforms
where long has 32 bits but int has only 16. Shifting by 24 on such a
platform is undefined behavior, and will almost certainly give the
wrong results.


True. An
assert(sizeof(int) == 4);
would secure the code.


Actually it wouldn't, eg. (8-bit signed char):
char b[4] = { 0x01, 0x02, 0x03, 0x99 };

Then 0x01020300 | 0x99 will become 0x01020300 | 0xFFFFFF99
which is not the desired result. You have to make the
chars unsigned before you apply bit operations to them.

Aug 8 '05 #17
Vincent wrote:
Thanks for this suggestion. It works! Somewhere else in my script, I
have to convert an unsigned long to a char[4]. I tried to use memcpy to
create a LongtoChararr function, but i failed. I'm not very familiar
with memcpy. Can you help me again?


If byte order is not essential, you can do reinterpret_cast again.

unsigned long ul = 0xFEDCBA98;
char *ptr = reinterpret_cast<char *>(&ul);

Depending upon endianness, you will end up with one of these:
ptr[] = {0xFE, 0xDC, 0xBA, 0x98}; // big endian machine
ptr[] = {0x98, 0xBA, 0xDC, 0xFE}; // little endian machine

Note if an unsigned long is not 4 bytes on the platform you're using,
you will end up with a different sized array.

If you really want to use memcpy,

unsigned long ul = 0xFEDCBA98;
char ptr[sizeof(unsigned long)];

memcpy(ptr, &ul, sizeof(unsigned long));

--John Ratliff
Aug 9 '05 #18
In message <11**********************@f14g2000cwb.googlegroups .com>,
ThosRTanner <tt******@bloomberg.net> writes
&x points to a number of bytes which contain (on a big endian machine,
LSB is at highest byte address) 0, 0, ... , 1, and (on a little endian
machine, LSB is at lowest byte address) 1, 0, ... 0

Interpreting the pointer as a char * and getting the byte pointed to
will return the contents of the lowest addressed byte of the word,
which will be 0 for big endian machines and 1 for little endian
machines.

Optimising out the code is presumably a result of gcc recognising that
particular pattern - it would be rather dangerous if you were cross
compiling!


It's rather dangerous anyway if your target platform has
sizeof(int)==sizeof(char).

--
Richard Herring
Aug 15 '05 #19

Vincent wrote:
Hi all,

I want to convert a char[4] (binary) to an unsigned long. How can I do
this?


My suggestion is to:
- always use big-endian regardless of platform
- use something like this:

const size_t CHAR_BITS = 8; // or whatever it is on your system

unsigned long makeLong( const char* data )
{
unsigned long result = 0;
for ( int i=0; i<4; ++i )
{
result <<= CHAR_BITS;
result |= data[i];
}
}

that will work whenever sizeof(long) >= 4 or there are sufficient
trailing 0 bytes that overflow does not occur.

Aug 15 '05 #20

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

Similar topics

3
by: Siemel Naran | last post by:
Hi. Is there a way to convert the type signed int to the type unsigned int, char to unsigned char, signed char to unsigned char, and so on for all the fundamental integer types? Something like ...
19
by: jeff | last post by:
how do you convert form byte to Int32 while retaining the binary value of the byte array
2
by: Goran | last post by:
Hi! I need to convert from a unsigned char array to a float. I don't think i get the right results in the program below. unsigned char array1 = { 0xde, 0xc2, 0x44, 0x23}; //I'm not sure in...
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...
7
by: whatluo | last post by:
Hi, all I'm now working on a program which will convert dec number to hex and oct and bin respectively, I've checked the clc but with no luck, so can anybody give me a hit how to make this done...
65
by: kyle.tk | last post by:
I am trying to write a function to convert an ipv4 address that is held in the string char *ip to its long value equivalent. Here is what I have right now, but I can't seem to get it to work. ...
24
by: cedarson | last post by:
I am having trouble writing a simple code that will convert an int ( 487 for example ) to binary form just for the sake of printing the binary. Can someone please help? Thanks!
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...
29
by: Kenzogio | last post by:
Hi, I have a struct "allmsg" and him member : unsigned char card_number; //16 allmsg.card_number
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
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
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.