G
Guest
I want convert a value in a signed integer into an unsigned integer of the
same size, with a linear value shift that converts the lowest signed value
into the lowest unsigned value, and converts the highest signed value into
the highest unsigned value.
For 8 bit: For 16 bit: For 32 bit:
-128 -> 0 -32768 -> 0 -2147483648 -> 0
-127 -> 1 -32767 -> 1 -2147483647 -> 1
-1 -> 127 -1 -> 32767 -1 -> 2147483647
0 -> 128 0 -> 32768 0 -> 2147483648
1 -> 129 1 -> 32769 1 -> 2147483649
126 -> 254 32766 -> 65534 2147483646 -> 4294967294
127 -> 255 32767 -> 65535 2147483647 -> 4294967295
You can figure out the values for 64 bit, or other sizes. For particular
code, I'll know the size and thus the value difference.
I also want to do the exact reverse.
I can do this if a larger integer type is available, but first converting
the (un)signed value to a larger signed integer, doing arithmetic to shift
the value range, then convert back to a smaller size of reverse
signedness.
code #1:
char a;
int b;
unsigned char c;
a = -5; /* or otherwise assigned by some means */
b = (int) a;
b += 128;
c = (unsigned char) b;
Now variable c will have the value 123. The reverse would be:
code #2:
unsigned char a;
int b;
char c;
a = 123; /* or otherwise assigned by some means */
b = (int) a;
b -= 128;
c = (char) b;
Now variable c will have the value -5.
This is not an available option with the largest available integer type.
However, the first conversion can still be done by using the definition in
C99 6.3.1.3.2, which forces all signed values to be transposed to values
in an unsigned integer type by means of adding or subtracting one larger
than the largest value of the unsigned type, and C99 6.2.5.9 which avoids
overflow in unsigned integer arithmetic by wrapping module one larger than
the largest possible value.
So for 32 bit long integers (pretending there is nothing larger to use):
code #3:
long a;
unsigned long b;
a = -5; /* or otherwise assigned by some means */
b = (unsigned long) a;
b += 2147483648;
Now variable b will have the value 2147483643.
The catch is that the reverse if THIS does not appear to be compliant with
C99 even though on the gcc x86 implementation it works:
code #4:
unsigned long a;
long b;
a = 2147483643; /* or otherwise assigned by some means */
a -= 2147483648;
b = (long) a;
Now variable b does end up having the value -5. But I do not see anything
in the C99 standard that says it will have that value.
My goal is to find something that will do the conversion described in #4,
for any size of integer (without using a larger size), in a way that always
reverses the conversion described in #3, and does so in compliance with the
definition of C99.
same size, with a linear value shift that converts the lowest signed value
into the lowest unsigned value, and converts the highest signed value into
the highest unsigned value.
For 8 bit: For 16 bit: For 32 bit:
-128 -> 0 -32768 -> 0 -2147483648 -> 0
-127 -> 1 -32767 -> 1 -2147483647 -> 1
-1 -> 127 -1 -> 32767 -1 -> 2147483647
0 -> 128 0 -> 32768 0 -> 2147483648
1 -> 129 1 -> 32769 1 -> 2147483649
126 -> 254 32766 -> 65534 2147483646 -> 4294967294
127 -> 255 32767 -> 65535 2147483647 -> 4294967295
You can figure out the values for 64 bit, or other sizes. For particular
code, I'll know the size and thus the value difference.
I also want to do the exact reverse.
I can do this if a larger integer type is available, but first converting
the (un)signed value to a larger signed integer, doing arithmetic to shift
the value range, then convert back to a smaller size of reverse
signedness.
code #1:
char a;
int b;
unsigned char c;
a = -5; /* or otherwise assigned by some means */
b = (int) a;
b += 128;
c = (unsigned char) b;
Now variable c will have the value 123. The reverse would be:
code #2:
unsigned char a;
int b;
char c;
a = 123; /* or otherwise assigned by some means */
b = (int) a;
b -= 128;
c = (char) b;
Now variable c will have the value -5.
This is not an available option with the largest available integer type.
However, the first conversion can still be done by using the definition in
C99 6.3.1.3.2, which forces all signed values to be transposed to values
in an unsigned integer type by means of adding or subtracting one larger
than the largest value of the unsigned type, and C99 6.2.5.9 which avoids
overflow in unsigned integer arithmetic by wrapping module one larger than
the largest possible value.
So for 32 bit long integers (pretending there is nothing larger to use):
code #3:
long a;
unsigned long b;
a = -5; /* or otherwise assigned by some means */
b = (unsigned long) a;
b += 2147483648;
Now variable b will have the value 2147483643.
The catch is that the reverse if THIS does not appear to be compliant with
C99 even though on the gcc x86 implementation it works:
code #4:
unsigned long a;
long b;
a = 2147483643; /* or otherwise assigned by some means */
a -= 2147483648;
b = (long) a;
Now variable b does end up having the value -5. But I do not see anything
in the C99 standard that says it will have that value.
My goal is to find something that will do the conversion described in #4,
for any size of integer (without using a larger size), in a way that always
reverses the conversion described in #3, and does so in compliance with the
definition of C99.