The following way of checking for the signed number representation checks for twos complement correctly on my machine, but I dont have ones complement or signed magnitude machines to check it. Would the code work properly and more importantly, is it portable?
File: platform.h
#ifndef PLATFORM_H
#define PLATFORM_H
#include <limits.h>
static
const union {
signed char sc;
unsigned char uc;
} plat_4xvYw = {.sc = -1};
#define IS_TWOS_COMPL (plat_4xvYw.uc == UCHAR_MAX)
#define IS_ONES_COMPL (plat_4xvYw.uc == UCHAR_MAX - 1)
#define IS_SIGNED_MAG (plat_4xvYw.uc == (1U << (CHAR_BIT - 1)) + 1U)
#endif
File: a.c
#include <inttypes.h>
#include <limits.h>
#include "platform.h"
#include <assert.h>
int
main (void) {
assert (IS_TWOS_COMPL);
if (IS_TWOS_COMPL) {
printf ("twos complement\n");
} else if (IS_ONES_COMPL) {
printf ("ones complement\n");
} else if (IS_SIGNED_MAG) {
printf ("signed magnitude\n");
}
return 0;
}
I think you're better off just masking the bits of a negative int
:
if ((-1 & 0x1) == 0) {
// -1 ends in "0" => 1s' complement
} else if ((-1 & 0x2) == 0) {
// -1 ends in "01" => sign-magnitude
} else {
// -1 ends in "11" => two's complement
}
Strictly speaking, this doesn't tell you the same thing as your code, since there's no guarantee that int
and signed char
use the same meaning of the sign bit. But (a) seriously? and (b) this works for types int
and larger, for smaller types it's trickier. unsigned char
is guaranteed to have no padding bits, but signed char
is not. So I think it's legal to have (for example) CHAR_BIT == 9
, UCHAR_MAX = 511
, CHAR_MAX = 127
, and signed char
has 1 padding bit. Then your code could fail: the sign bit in the stored signed value isn't necessarily where you expect it to be, and the value of the padding bit could be either 0 or 1.
In a lot of cases you could just use int8_t
in the program instead of signed char
. It's guaranteed to be 2's complement if it exists, so might save you from caring about the representation of signed char
. If it doesn't exist, the program won't compile, which is kind of what you're assert
ing anyway. You'd get a false negative from platforms which are 2's complement, but don't have an 8-bit char and therefore do not provide int8_t
. This may or may not bother you...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With