问题
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;
}
回答1:
To find negative 0's just check for a zero with any bit at all set.
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 may not work for even more esoteric ones.
回答2:
Not sure exactly what you are asking. If you asking 'How do we determine if a machine is ones-complement, twos-complement, or sign-magnitude?' you can use:
if (1 & -1) {
if (3 & -1 == 1)
printf("sign magnitude\n");
else
printf("twos complement\n");
} else
printf("ones complement\n");
回答3:
Your question is a bit confusing. Do you know the encoding ahead of time? If not, what you are is asking is impossible, as the mappings are different for different encodings. For example, the byte 1111111
, has a "sign" of 0 in one's complement but a sign of -1 in two's complement. So how can there be a universal way to check if they are defined differently?
EDIT: You might be able to cheat:
int sign(int x)
{
if (x > 0) return 1;
if (x > -1) return 0;
return -1;
}
来源:https://stackoverflow.com/questions/19869976/how-to-uniformly-detect-an-integer-s-sign-bit-across-various-encodings-1s-comp