views:

155

answers:

6

The ISO C standard allows three encoding methods for signed integers: two's complement, one's complement and sign/magnitude.

What's an efficient or good way to detect the encoding at runtime (or some other time if there's a better solution)? I want to know this so I can optimise a bignum library for the different possibilities.

I plan on calculating this and storing it in a variable each time the program runs so it doesn't have to be blindingly fast - I'm assuming the encoding won't change during the program run :-)

+11  A: 

Detecting one's complement should be pretty simple -- something like if (-x == ~x). Detecting two's complement should be just about as easy: if (-x == ~x + 1). If it's neither of those, then it must be sign/magnitude.

Jerry Coffin
These are constant expressions too, so you can use them in `#if` tests: `#define TWOSCOMPLEMENT (~-1 == 0)` then `#if TWOSCOMPLEMENT`.
caf
your expressions are not necessarily true for all cases of `x` though, so you should be careful with border cases. In particular there is this nasty case for two's complement where `-x` provokes undefined behavior, namely `-INT_MIN` may be out of bounds.
Jens Gustedt
+3  A: 

Why not do it at compile time? You could have the build scripts/makefile compile a test program if need be, but then use the preprocessor to do conditional compilation. This also means performance is much less important, because it only runs once per compile, rather than once per run.

Matthew Flaschen
A: 

I guess you'd store a negative number as an int into a char array large enough to hold it and compare the array with the various representations to find out.

But uhm... unsigned integers should not have a sign, do they ?

Archimedix
Yeah... seems I was thinking too complicated... Jerry's right about using bit operations to check. Never mind. Leaving it here as an alternative answer.
Archimedix
Yeah, sorry, that should have been signed.
paxdiablo
A: 

Get a pointer to to an int that would show a distinctive bit-pattern. Cast it as a pointer to unsigned int and then examine the bit values.

Doing this with a couple of carefully chosen values should do what you want.

Andrew Cooper
+10  A: 

You just have to check the low order bits of the constant -1 with something like -1 & 3. This evaluates to

  1. for sign and magnitude,
  2. for one's complement and
  3. for two's complement.

This should even be possible to do in a preprocessor expression inside #if #else constructs.

Jens Gustedt
+1  A: 

Here is some more info:

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

I'd go with Jens' answer and examine the lowest two bits of -1.

Secure