How to detect an int
sign-ness in C?
This question is mostly of historical machines. What I am asking how to distinguish if an integer is 0 or -0. In 1's complement and sign/magnitude int encoding, both a 0 (or +0) and -0 are possible.
The simple sign bit test is to compare against 0
.
int x;
printf("sign bit is %s\n", (x < 0) ? "set" : "not set");
But this fails in 1's complement and sign magnitude when x
is -0
.
1st Candidate approach: Mask test.
As C defines that an int
must have a sign bit regardless of integer encoding, the following should work.
int x;
int SignBitMask = tbd;
printf("sign bit is %s\n", (x & SignBitMask) ? "set" : "not set");
The question becomes how to determine the value of SignBitMask
in C?
SignBitMask = INT_MAX + 1
seems like a starting point.
2nd Candidate approach: create 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'm thinking there is no portable uniform solution - maybe because the need no longer exists.
Why: I have wondered how various signed zeros were detected and printed.
Note: I have purposely avoided the "C" tag here and thought I'd try just the "History" tag first.
[Edit] Answer
Combining info of 3 answers and C11dr 6.2.6.2 "Integer types" (for int
, a single sign bit must exist, the positive sign bit is 0, the negative sign bit is 1), a solution (that appears independent of 1's complement, 2's complement and sign/magnitude integer encoding) 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 direct mask approach is simplest, but have not come up with a highly portable mask definition
int IsSignBitSet_Simple(int x) {
static unsigned SignBitMask = 0x80; // Or some other platform dependent mask
return ((unsigned)x & SignBitMask) != 0;
}