Most negative double value

C

Christian Bau

Papadopoulos Giannis said:
Yes, this is right if I am writing robust code to run everywhere... On
the other hand this is a really simple (and maybe stupid) program that
tries to find machine endianess and is part of my signature...


OK, but all the great minds of processor design have come to the
conclusion that the 16bit integer will be represented in either big
endian or little endian...

comp.lang.c is about portable C. Using non-portable C in your signature
on comp.lang.c is not too clever.
PS even with padding bits, I think *(char*)&v==1 should do the trick...
comments?

With padding bits, *(char*)&v might read padding bits and nothing else,
so the result could be anything at all. Of course, if you have padding
bits then you would have to define what you call "bigendian" and what
you call "littleendian" first.
 
C

Christian Bau

Papadopoulos Giannis said:
Arthur said:
I.e., it's not pragmatic or correct. Which will attract attention
in comp.lang.c, because that's the kind of thing we do here. :) If
you don't want comments on your sig, then you should not post your
sig to comp.lang.c.

I've never said I do not want comments on what I'm writing.. Comments
are always acceptable...
Wrong. Assuming 'v' is an int, you're invoking undefined behavior
by trying to look at its bits as if they represented a valid 'char'
value. So anything can happen, including nasal demons or wrong
answers.

-Arthur

For a 32-bit machine would

union boo {
unsigned int i;
unsigned char c[4];
};

union boo a;

and looking at a.c[0]

be more acceptable??

That doesn't make the slightest difference. The problem is that the
value bits in the unsigned int could be mapped to the value bits in the
unsigned chars in an arbitrary way.
 
K

Keith Thompson

Arthur J. O'Dwyer said:
Anyway, the basic point I guess is that you haven't fully defined
what you mean by "endianness." Sure, there are two or three obvious
"endian" cases, but how do you classify the big gray area including
padding bits and weird bit orders?
If you assume as a prerequisite that the implementation *must*
have either the 1234 or the 4321 byte order, and no padding bits,
then your program works perfectly. But standard C doesn't make that
assumption -- it makes different assumptions such that it is actually
impossible to determine whether a given 'int' is big- or little-endian
in a portable fashion. (I'm fairly sure that's right -- something
like the Halting Problem probably applies somehow.)

I hardly think that the Halting Problem is relevant. In the very
worst case, you could iterate over all possible unsigned int values,
viewing each one as an array of unsigned char and testing whether it
matches the sequence you'd get from a straighforward big-endian or
little-endian representation. There are three possibilities:

1. All values are stored as big-endian.
2. All values are stored as little-endian.
3. Something else.

The "something else" case is likely to be rare in practice. That
doesn't mean you can ignore it, but it does mean you can reasonably
write your program so it fails (as early as possible) if the platform
doesn't meet condition 1 or 2.

In fact, I'm fairly sure that you don't need to iterate over all
unsigned int values; the language provides enough guarantees about
binary representation that you can take some significant shortcuts.
(I'm not sure exactly what those shortcuts are.)
 
C

Christian Bau

Keith Thompson said:
In fact, I'm fairly sure that you don't need to iterate over all
unsigned int values; the language provides enough guarantees about
binary representation that you can take some significant shortcuts.
(I'm not sure exactly what those shortcuts are.)

If there are no padding bits then all you need to do is store the values
1u << n for 0 <= n < CHAR_BITS * sizeof (unsigned int) and check where
they turn up. If there are padding bits, then it is possible that one of
the padding bits and one of the value bits have the same value whenever
you look at them, so they are impossible to distinguish.
 
P

Papadopoulos Giannis

Christian said:
comp.lang.c is about portable C. Using non-portable C in your signature
on comp.lang.c is not too clever.

Portable code => good code, but bad logic... :(
With padding bits, *(char*)&v might read padding bits and nothing else,
so the result could be anything at all. Of course, if you have padding
bits then you would have to define what you call "bigendian" and what
you call "littleendian" first.

Hmmm, I thought all of this and for the time being I do not see a viable
solution... Looking for a new signature already...
 
G

glen herrmannsfeldt

Dan Pop wrote:

(someone wrote)
Because the standard uses a sign-magnitude model for the floating point
numbers. 5.2.4.2.2 in C99. Sorry, but the text is next to impossible
to quote in plain text format, without using some special convention,
a la TeX and friends.

There are machines that use twos complement for floating point,
though I don't like it much.

The PDP-10 uses the twos complement of the entire word for negative
floating point, which apparently allows them to use the integer
compare instructions on float values. Otherwise, it seems strange
to mix the mantissa and exponent bits which can happen in certain cases.

-- glen
 
C

CBFalconer

glen said:
Dan Pop wrote:
(someone wrote)



There are machines that use twos complement for floating point,
though I don't like it much.

The PDP-10 uses the twos complement of the entire word for negative
floating point, which apparently allows them to use the integer
compare instructions on float values. Otherwise, it seems strange
to mix the mantissa and exponent bits which can happen in certain
cases.

Almost 30 years ago I wrote a FP package to use 2's complement.
You can see the result if you can find the Intel 8080 user
contribution library from back then. The complications were
astounding. I rebuilt it the next year to use sign/magnitude with
suppressed leading bit, and things were greatly simplified, and
the performance roughly tripled. Accuracy was also improved.
 
D

Dan Pop

In said:
Dan Pop wrote:

(someone wrote)


There are machines that use twos complement for floating point,
though I don't like it much.

Do they have conforming C implementations?

Dan
 
D

Dan Pop

In said:
Do you think that bigendian and littleendian are the only possibilities?

The only ones worth worrying about on modern hosted implementations.
If these are the only byte orders with a well defined name, there must
be a reason.
Could the char that you are reading consist completely of padding bits
in the int, in which case you could get two different results when you
run the program twice?

Yeah, but the compiler doing it this way takes one million years to
compile the simplest C source code.

Dan
 
M

Mark L Pappin

Long ago said:
#include <stdio.h>
#define p(s) printf(#s" endian")
int main(void){int v=1;*(char*)&v?p(Little):p(Big);return 0;}

(and there was much wailing and gnashing of teeth)

Having seen much discussion about differend endinannesses than plain
old "big" and "little", and the possibility of padding bits or
arbitrary bit mappings, I put the following together.

#include <stdio.h>
#include <limits.h>

int main(void)
{
unsigned u = 1;
unsigned failsafe = CHAR_BIT * sizeof u + 1;
while (u && failsafe--) {
unsigned i;
if (!failsafe) {
printf("Odd: u == %x\n",u);
break;
}
for (i = 0; i < sizeof u; i++) {
printf("%s%02x",
i? ":": "",
(unsigned)(((unsigned char*)&u)));
}
putchar('\n');
u <<= 1;
}
return 0;
}

Is there any chance of UB here?

mlp
 
C

Christian Bau

Mark L Pappin said:
Long ago said:
#include <stdio.h>
#define p(s) printf(#s" endian")
int main(void){int v=1;*(char*)&v?p(Little):p(Big);return 0;}

(and there was much wailing and gnashing of teeth)

Having seen much discussion about differend endinannesses than plain
old "big" and "little", and the possibility of padding bits or
arbitrary bit mappings, I put the following together.

#include <stdio.h>
#include <limits.h>

int main(void)
{
unsigned u = 1;
unsigned failsafe = CHAR_BIT * sizeof u + 1;
while (u && failsafe--) {
unsigned i;
if (!failsafe) {
printf("Odd: u == %x\n",u);
break;
}
for (i = 0; i < sizeof u; i++) {
printf("%s%02x",
i? ":": "",
(unsigned)(((unsigned char*)&u)));
}
putchar('\n');
u <<= 1;
}
return 0;
}

Is there any chance of UB here?


CHAR_BIT could be greater than eight, but %02x will print the number
anyway, so you should be fine.

If you look at the output, you can check all the bits in a
representation and decide:

1. A bit in the representation that was never set or set more than once
is definitely a padding bit. A bit in the representation that was set
exactly once could be a value bit or a padding bit.

2. If in line k of your output bit j is the only bit that is a possible
value bit, then bit j in the representation is the value bit
representing bit k in an unsigned int.

3. With the output of this program, you might not be able to decide
which bit in the representation represents a certain bit in an unsigned
int. That would happen if one padding bit is set only once during
execution of your program.

A sixteen bit unsigned int could be stored in 32 bits with 16 padding
bits, and the hardware could set the padding bits equal to the value
bits except on April 1st. To decide which bits are value bits you would
have to wait until April 1st.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top