Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Write int as a 4 byte big-endian to file.

Reply
Thread Tools

Write int as a 4 byte big-endian to file.

 
 
MS
Guest
Posts: n/a
 
      03-10-2012
Hi,

I need some help with something which is a little over my pay grade.

The file which I must write has a header followed by a sequence of ints
each of which must be written as a 4 byte big-endian.

The comp.lang.c has advice on finding out whether your machine is
little-endian or big-endian (little-endian in my case) but not on how to
do the kind of operation I need to do.

I am sorry to say that I simply have no idea whatsoever how to write an
int to a file as a 4 byte big-endian. Can someone show me how please?

Many thanks.
 
Reply With Quote
 
 
 
 
Don Y
Guest
Posts: n/a
 
      03-10-2012
On 3/10/2012 11:00 AM, MS wrote:
> I need some help with something which is a little over my pay grade.
>
> The file which I must write has a header followed by a sequence of ints
> each of which must be written as a 4 byte big-endian.
>
> The comp.lang.c has advice on finding out whether your machine is
> little-endian or big-endian (little-endian in my case) but not on how to
> do the kind of operation I need to do.
>
> I am sorry to say that I simply have no idea whatsoever how to write an
> int to a file as a 4 byte big-endian. Can someone show me how please?


Break the 4 byte value into 4 *bytes*. Then, write them
INDIVIDUALLY in Big Endian order.
 
Reply With Quote
 
 
 
 
MS
Guest
Posts: n/a
 
      03-10-2012
On 10/03/12 18:11, Don Y wrote:
> On 3/10/2012 11:00 AM, MS wrote:
>> I need some help with something which is a little over my pay grade.
>>
>> The file which I must write has a header followed by a sequence of ints
>> each of which must be written as a 4 byte big-endian.
>>
>> The comp.lang.c has advice on finding out whether your machine is
>> little-endian or big-endian (little-endian in my case) but not on how to
>> do the kind of operation I need to do.
>>
>> I am sorry to say that I simply have no idea whatsoever how to write an
>> int to a file as a 4 byte big-endian. Can someone show me how please?

>
> Break the 4 byte value into 4 *bytes*. Then, write them
> INDIVIDUALLY in Big Endian order.


Ahh yes. That is exactly how far I got on my own. Sorry to be a bit
clueless but I don't know how to accomplish that.

I'm also worried about the code being endian specific, the code must
work regardless of whether the machine is little-endian or big-endian,
but I already know how to test which the machine is thanks to the FAQ.

Since it has just occurred to me I should also mention that my int range
is from 0 to potentially the low tens of millions.

Thanks (and sorry for bothering you guys, I have done several web
searches and can't find any page/post that spells it out for me, I was
surprised it isn't in the FAQ - that usually sorts me out).
 
Reply With Quote
 
Bl0ckeduser
Guest
Posts: n/a
 
      03-10-2012
MS wrote:
> Hi,
>
> I need some help with something which is a little over my pay grade.
>
> The file which I must write has a header followed by a sequence of ints
> each of which must be written as a 4 byte big-endian.
>
> The comp.lang.c has advice on finding out whether your machine is
> little-endian or big-endian (little-endian in my case) but not on how to
> do the kind of operation I need to do.
>
> I am sorry to say that I simply have no idea whatsoever how to write an
> int to a file as a 4 byte big-endian. Can someone show me how please?
>
> Many thanks.


Hi, I'm not a C expert, but the following worked for me on a low-endian
32-bit machine, a low-endian 64-bit machine, and a big-endian 32-bit
machine:

int i = 12345678;
printf("%d\n", (i & 0xFF000000) >> 32);
printf("%d\n", (i & 0x00FF0000) >> 16);
printf("%d\n", (i & 0x0000FF00) >> ;
printf("%d\n", i & 0x000000FF);

output (identical on all three machines):

0
188
97
78


 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      03-10-2012
MS <ms@no_spam_thanks.com> writes:

> The file which I must write has a header followed by a sequence of
> ints each of which must be written as a 4 byte big-endian.
>
> The comp.lang.c has advice on finding out whether your machine is
> little-endian or big-endian (little-endian in my case) but not on how
> to do the kind of operation I need to do.
>
> I am sorry to say that I simply have no idea whatsoever how to write
> an int to a file as a 4 byte big-endian. Can someone show me how
> please?


To write:

void
write_four_bytes_in_MSB_first_order( FILE *file, unsigned long what ){
int i;
unsigned char bytes[4];
for( i = 3; i >= 0; i-- ) bytes[i] = what % 256, what /= 256;
for( i = 0; i <= 3; i++ ) fputc( bytes[i], file );
}

Although the 'what' parameter is unsigned long, giving an int or
long int argument will work fine provided the signed value fits
in four bytes. The value will be written using a two's complement
representation.



To read:

long int
read_four_bytes_in_MSB_first_order( FILE *file ){
unsigned long bits;
int i;
for( bits = 0, i = 0; i < 4; i++ ) bits = bits*256 + fgetc( file );

return bits < 0x80000000 ? bits : -1 - (long)(bits ^ 0xffffffff);
}

The last part of the return expression guarantees the value can be
read even on machines that don't use two's complement (assuming
the value isn't the most negative two's complement value, which
cannot be represented in the two other representations).
 
Reply With Quote
 
Sjouke Burry
Guest
Posts: n/a
 
      03-10-2012
MS <ms@no_spam_thanks.com> wrote in news:mFM6r.21733$di4.7072
@newsfe14.ams2:

> Hi,
>
> I need some help with something which is a little over my pay grade.
>
> The file which I must write has a header followed by a sequence of ints
> each of which must be written as a 4 byte big-endian.
>
> The comp.lang.c has advice on finding out whether your machine is
> little-endian or big-endian (little-endian in my case) but not on how

to
> do the kind of operation I need to do.
>
> I am sorry to say that I simply have no idea whatsoever how to write an
> int to a file as a 4 byte big-endian. Can someone show me how please?
>
> Many thanks.
>

Hm... just reverse the routine below....

int little_endian(char *c){
static union{
int k;
char c[4];
}p;
p.c[0]=c[3];
p.c[1]=c[2];
p.c[2]=c[1];
p.c[3]=c[0];
return p.k;
}
 
Reply With Quote
 
Morris Keesan
Guest
Posts: n/a
 
      03-10-2012
On Sat, 10 Mar 2012 13:00:50 -0500, MS <ms@no_spam_thanks.com> wrote:

> Hi,
>
> I need some help with something which is a little over my pay grade.
>
> The file which I must write has a header followed by a sequence of ints
> each of which must be written as a 4 byte big-endian.
>
> The comp.lang.c has advice on finding out whether your machine is
> little-endian or big-endian (little-endian in my case) but not on how to
> do the kind of operation I need to do.
>
> I am sorry to say that I simply have no idea whatsoever how to write an
> int to a file as a 4 byte big-endian. Can someone show me how please?


We'll assume that this means 4 8-bit bytes.

First, make sure that it will fit:
assert((sizeof(int) * CHAR_BIT) <= 32);
Then put the value into a (unsigned long int), so that you're guaranteed
to be working with an object which is at least 32 bits long, and you don't
have to worry about the implementation-defined results of applying
the >> operator to a signed quantity.
Then simply use bitwise operations (shifting and masking) to pick out
the successive octets of the low-order 32 bits of the int, starting from
the highest-order octet of those 32 bits.

unsigned long int ltemp = intvalue;
for (int i = 0; i < 3; ++i)
fputc((intvalue >> (8 * (3 - i))) & 0xff, file);

Because you're working purely with the numerical value of the number,
this should work regardless of the endianness of the platform you're
doing this on.
--
Morris Keesan -- http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Stephen Sprunk
Guest
Posts: n/a
 
      03-10-2012
On 10-Mar-12 12:36, MS wrote:
> On 10/03/12 18:11, Don Y wrote:
>> On 3/10/2012 11:00 AM, MS wrote:
>>> I need some help with something which is a little over my pay grade.
>>>
>>> The file which I must write has a header followed by a sequence of ints
>>> each of which must be written as a 4 byte big-endian.
>>>
>>> The comp.lang.c has advice on finding out whether your machine is
>>> little-endian or big-endian (little-endian in my case) but not on how to
>>> do the kind of operation I need to do.
>>>
>>> I am sorry to say that I simply have no idea whatsoever how to write an
>>> int to a file as a 4 byte big-endian. Can someone show me how please?

>>
>> Break the 4 byte value into 4 *bytes*. Then, write them
>> INDIVIDUALLY in Big Endian order.

>
> Ahh yes. That is exactly how far I got on my own. Sorry to be a bit
> clueless but I don't know how to accomplish that.


You seem to be hung up on how to extract individual bytes from a wider
type, which is typically done by shifting and masking; this would be the
canonical method:

unsigned long x = 0x12345678UL;
unsigned char bytes[4];

bytes[0] = (x >> 24) ; // 0x12
bytes[1] = (x >> 16) & 0xFF; // 0x34
bytes[2] = (x >> & 0xFF; // 0x56
bytes[3] = (x ) & 0xFF; // 0x78

Now you can write the bytes to your file. If the output needs to be
big-endian, write from 0 to 3; if little-endian, write from 3 to 0.

Of course, there is no need for the temporary variables if you can
inline the shifting and masking as arguments to the output function, but
the above should make it more clear _to you_ what's going on.

(There are other solutions, but I recommend against using them until you
fully understand how to do it "the hard way" as above.)

> I'm also worried about the code being endian specific, the code must
> work regardless of whether the machine is little-endian or big-endian,
> but I already know how to test which the machine is thanks to the FAQ.


The code above will work regardless of the endianness of the machine.
It does assume 8-bit chars, but a general solution that works with any
valid char width is messy and rarely necessary.

> Since it has just occurred to me I should also mention that my int range
> is from 0 to potentially the low tens of millions.


MAX_INT is only guaranteed to be 32767; if you need values larger than
that, use long (or long long) int rather than plain int.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      03-10-2012
On 3/10/2012 1:36 PM, MS wrote:
> On 10/03/12 18:11, Don Y wrote:
>> On 3/10/2012 11:00 AM, MS wrote:
>>> [...]
>>> I am sorry to say that I simply have no idea whatsoever how to write an
>>> int to a file as a 4 byte big-endian. Can someone show me how please?

>>
>> Break the 4 byte value into 4 *bytes*. Then, write them
>> INDIVIDUALLY in Big Endian order.

>
> Ahh yes. That is exactly how far I got on my own. Sorry to be a bit
> clueless but I don't know how to accomplish that.
>
> I'm also worried about the code being endian specific, the code must
> work regardless of whether the machine is little-endian or big-endian,
> but I already know how to test which the machine is thanks to the FAQ.


Don't bother testing: Just use the values.

putc(value & 0xFF, stream);
putc((value >> & 0xFF, stream);
putc((value >> 16) & 0xFF, stream);
putc((value >> 24) & 0xFF, stream);

Works[*] with BigEndian, LittleEndian, MiddleEndian, TightEndian,
EndOverEndian, and NimzoEndian architectures.

> Since it has just occurred to me I should also mention that my int range
> is from 0 to potentially the low tens of millions.


Although systems with narrow `int' are becoming rare, there
may be a few left. You may wish to take countermeasures, because
if you don't Murphy's Law will surely bite you. Instead of `int'
(which could top out at 32767 on some machines), use a wider type
like `long' (good up to at least 2147483647).[*]
[*] To avoid trouble with negative values, where shifting and
bitwise operations are problematic, prefer an `unsigned' type.

> Thanks (and sorry for bothering you guys, I have done several web
> searches and can't find any page/post that spells it out for me, I was
> surprised it isn't in the FAQ - that usually sorts me out).


Question 10.16 talks about testing for endianness, but also
has a pointer to Question 12.42 and its endian-independent code.

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      03-10-2012
On 3/10/2012 3:20 PM, Eric Sosman wrote:
> On 3/10/2012 1:36 PM, MS wrote:
>> On 10/03/12 18:11, Don Y wrote:
>>> On 3/10/2012 11:00 AM, MS wrote:
>>>> [...]
>>>> I am sorry to say that I simply have no idea whatsoever how to write an
>>>> int to a file as a 4 byte big-endian. Can someone show me how please?
>>>
>>> Break the 4 byte value into 4 *bytes*. Then, write them
>>> INDIVIDUALLY in Big Endian order.

>>
>> Ahh yes. That is exactly how far I got on my own. Sorry to be a bit
>> clueless but I don't know how to accomplish that.
>>
>> I'm also worried about the code being endian specific, the code must
>> work regardless of whether the machine is little-endian or big-endian,
>> but I already know how to test which the machine is thanks to the FAQ.

>
> Don't bother testing: Just use the values.
>
> putc(value & 0xFF, stream);
> putc((value >> & 0xFF, stream);
> putc((value >> 16) & 0xFF, stream);
> putc((value >> 24) & 0xFF, stream);


Aw, snap: This produces LittleEndian "wire format," and you
wanted BigEndian. Just reverse the four calls -- or read the
code from bottom to top.

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: byte + byte -> int Lew Java 6 03-21-2009 02:22 AM
how to read/write a characters stream which is either of one byte/2 byte Deep C Programming 6 02-28-2007 01:03 PM
read/write data byte-per-byte to and from a socket crash.test.dummy Java 1 02-17-2006 06:18 AM
int main(int argc, char *argv[] ) vs int main(int argc, char **argv ) Hal Styli C Programming 14 01-20-2004 10:00 PM
dirty stuff: f(int,int) cast to f(struct{int,int}) Schnoffos C Programming 2 06-27-2003 03:13 AM



Advertisments