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;
}

      

+2


source to share


3 answers


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.

+2


source


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");

      

+1


source


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;
}

      

+1


source







All Articles