Endianness and streams

K

kelvSYC

This seems to be easy, and perhaps I'm overthinking it a bit.
Anyways...

I want to use streams to write an int in binary form as a little-endian
byte sequence. Firstly, is the easiest way simply to put the int in a
temporary buffer, then write() the buffer? Secondly, does this count
as formatting (and thus using a custom fstream for binary output with a
customized << operator is justified)?
 
B

Bob Hairgrove

This seems to be easy, and perhaps I'm overthinking it a bit.
Anyways...

I want to use streams to write an int in binary form as a little-endian
byte sequence. Firstly, is the easiest way simply to put the int in a
temporary buffer, then write() the buffer? Secondly, does this count
as formatting (and thus using a custom fstream for binary output with a
customized << operator is justified)?

It depends on sizeof(int) on your machine. At any rate, you will get
the same results regardless of platform running the code by writing
(n%256) first, (n/256)%256 second, etc. until you hit 0. Also, replace
256 with 2**CHAR_BIT (using Fortran notation here) for your platform.
If you want big-endian, you need to write the bytes the other way
around.

For writing using ofstream, open the stream using the
std::ios_base::binary mode argument, fill your buffer and call
ofsteam::write() as many times as needed.
 
B

Bob Hairgrove

It depends on sizeof(int) on your machine. At any rate, you will get
the same results regardless of platform running the code by writing
(n%256) first, (n/256)%256 second, etc. until you hit 0.

Actually, you have to write sizeof(int) bytes even if value==0 for the
higher bytes, of course. And it's probably a good idea to cast the
input to unsigned int before doing mod which is meaningful only for
positive numbers.
 
P

Pete Becker

Bob said:
Actually, you have to write sizeof(int) bytes even if value==0 for the
higher bytes, of course. And it's probably a good idea to cast the
input to unsigned int before doing mod which is meaningful only for
positive numbers.

The % operator is meaningful for negative numbers. It's not the same as
mod, but there's no mod operator in C or in C++. When you have a
negative number for the numerator and a positive number for the
denominator you have the possibility that the result of % will be
negative. If that happens and you want a positive value you have to add
the denominator to the result.

Of course, for the original problem, you're right that you should treat
the bit pattern as an unsigned value. Not because % isn't meaningful,
but because using it in this case is harder when you have to deal with
negative values.
 
B

Bob Hairgrove

This seems to be easy, and perhaps I'm overthinking it a bit.
Anyways...

I want to use streams to write an int in binary form as a little-endian
byte sequence. Firstly, is the easiest way simply to put the int in a
temporary buffer, then write() the buffer? Secondly, does this count
as formatting (and thus using a custom fstream for binary output with a
customized << operator is justified)?

BTW, what if your::sizeof(int) != other::sizeof(int) (other:: being
the receiving end, of course)?

We are living in a time of transition from 32-bit to 64-bit ...
something to think about!
 
B

Bob Hairgrove

The % operator is meaningful for negative numbers. It's not the same as
mod, but there's no mod operator in C or in C++. When you have a
negative number for the numerator and a positive number for the
denominator you have the possibility that the result of % will be
negative. If that happens and you want a positive value you have to add
the denominator to the result.

Of course, for the original problem, you're right that you should treat
the bit pattern as an unsigned value. Not because % isn't meaningful,
but because using it in this case is harder when you have to deal with
negative values.

Thanks, Pete ... I wasn't aware that the % operator was not the same
as mod(ulo), although I find it obvious that it was meant to be that
way (perhaps mistakenly so). I always took the precaution of casting
the input to unsigned anyway, "just in case", so I never ran into
possible differences.

Since you say that operator % is indeed "meaningful" for negative
numbers, can you point me to someplace in the standard where the
meaning of this meaningfulness is defined? (this very much reminds me
of Clinton's "definition of *is*" <g>)

Cheers...
 
P

Pete Becker

Bob said:
Since you say that operator % is indeed "meaningful" for negative
numbers, can you point me to someplace in the standard where the
meaning of this meaningfulness is defined?

<g> 5.6/4.

The definition of % is that (a/b)*b + a%b == a. When both a and b are
non-negative the remainder is required to be non-negative. Otherwise,
the sign is implementation-defined.

The reason it's defined that way is to allow division and remainder to
be done in whatever way the underlying hardware does them. When both a
and b are positive there's no confusion. When a is negative and b is
positive the result of a/b can be rounded up or down, and a%b has to
match. For example, -5/3 can be -1 or -2, and 5%-3 is then -2 or +1,
respectively.
 
B

Bob Hairgrove

When a is negative and b is
positive the result of a/b can be rounded up or down, and a%b has to
match. For example, -5/3 can be -1 or -2, and 5%-3 is then -2 or +1,
respectively.

Absolutely mind-boggling ... I had no idea ... I wonder how much code
out there depends on this (implementation-defined) behavior??

Thanks, Pete.
 
P

Pete Becker

Bob said:
Absolutely mind-boggling ... I had no idea ... I wonder how much code
out there depends on this (implementation-defined) behavior??

None, I hope. <g>
 

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

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top