How to evenly determine the sign bit of integers in different encodings (1's complement, 2's complement, signed value)?
How do you detect a character int
in C?
This question mostly pertains to historical machines. I am asking how to distinguish an integer from 0 or -0. In 1's complement encoding with signs / values, both 0 (or +0) and -0 are possible.
A simple sign bit test is to compare with 0
.
int x;
printf("sign bit is %s\n", (x < 0) ? "set" : "not set");
But it doesn't match 1's complement and sign value when x
-0
.
1st candidate approach: mask test.
Since C specifies what the int
sign bit should have, regardless of the integer encoding, the following should work.
int x;
int SignBitMask = tbd;
printf("sign bit is %s\n", (x & SignBitMask) ? "set" : "not set");
The question is, how do you define a value SignBitMask
in C? SignBitMask = INT_MAX + 1
seems like a starting point.
Second candidate approach: create a function and check bit patterns:
int IsSignBitSet(int x) {
if (x > 0) return 0;
if (x < 0) return 1;
int zp = 0;
if (memcmp(&x, &zp, sizeof x) == 0) return 0;
int zn = -0; // Is this even the way to form a -0?
if (memcmp(&x, &zn, sizeof x) == 0) return 1;
// If we get here, now what?
return ?;
}
I think there is no portable uniform solution - maybe because it is no longer required.
Why: I wondered how the various signed zeros were detected and printed.
Note. I deliberately avoided the "C" tag and thought I would only try the "History" tag first.
[Edit] Answer
Combination of information from 3 answers and C11dr 6.2.6.2 "Integer types" (for int
must have one sign bit, positive sign bit is 0, negative sign bit - 1), solution (which appears regardless of 1's complement, 2's complement and integer sign encoding / value) is
int IsSignBitSet_Best(int x) {
// return 1 if x is less than 0 _or_ x is arithmetically 0 with some bit set.
return (x < 0) || ((x == 0) && (* ((unsigned int*) &x) ));
}
The straight mask approach is the simplest, but does not have a very portable mask definition
int IsSignBitSet_Simple(int x) {
static unsigned SignBitMask = 0x80; // Or some other platform dependent mask
return ((unsigned)x & SignBitMask) != 0;
}
source to share
To find a negative 0, just check for zero with any bit at all settings.
int testForNegative0(int x) {
return (x==0 && *((unsigned int*)&x));
}
Or to answer the question in the title:
int hasSignBitSet(int x) {
return (x<0) || testForNegative0(x);
}
This works for the 3 encodings you mention, it might not work for even more esoteric ones.
source to share
Not sure what exactly you are asking. If you ask: "How do we determine whether a car is a unit, complement, two complements, or a sign value?" you can use:
if (1 & -1) {
if (3 & -1 == 1)
printf("sign magnitude\n");
else
printf("twos complement\n");
} else
printf("ones complement\n");
source to share
Your question is a little confusing. Do you know the encoding ahead of time? If not, what you are asking is not possible, since the mappings are different for different encodings. For example, a byte 1111111
has a "0" in one's complement, but a -1 in two's complement. So how could there be a universal way to check if they are defined differently?
EDIT: maybe you can cheat:
int sign(int x)
{
if (x > 0) return 1;
if (x > -1) return 0;
return -1;
}
source to share