Reputation: 59
I have a strange problem. I have a variable whose actual value is only negative(only negative integers are generated for this variable). But in the legacy code, an old colleague of mine used uint16 instead of signed int to store the values of that variable. Now if i wanted to print the actual negative value of that variable, how can i do that(what format specifier to us)? For example if actual value is -75, when i print using %d its giving me 5 digit positive value(I think its because of two's complement). I want to print it as 75 or -75.
Upvotes: 0
Views: 3739
Reputation: 81143
If u
is an object of unsigned integer type and a negative number whose magnitude is within range of u
's type is stored into it, storing -u
to an object of u
's type will leave it holding the magnitude of that negative number. This behavior does not depend upon how u
is represented. For example, if u
and v
are 16-bit unsigned short
, but int
is 32 bits, then storing -60000 into u
will leave it holding 5536
[the implementation will behave as though it adds 65536 to the value stored until it's within range of unsigned short
]. Evaluating -u
will yield -5536, and storing -5536 into v
will leave it holding 60000.
Upvotes: 0
Reputation: 9203
Assuming your friend has somehow correctly put the bit representation for the signed integer into the unsigned integer, the only standard compliant way to extract it back would be to use a union as-
typedef union {
uint16_t input;
int16_t output;
} aliaser;
Now, in your code you can do -
aliaser x;
x.input = foo;
printf("%d", x.output);
Upvotes: 1
Reputation: 222427
If a 16-bit negative integer was stored in a uint16_t
called x
, then the original value may be calculated as x-65536
.
This can be printed with any of1:
printf("%ld", x-65536L);
printf("%d", (int) (x-65536));
int y = x-65536;
printf("%d", y);
Subtracting 65536 works because:
uint16_t
, one more than its maximum is 65536.uint16_t
.1 65536
will be long
or int
according to whether int
is 16 bits or more, so these statements are careful to handle the type correctly. The first uses 65536L
to ensure the type is long
. The rest convert the value to int
. This is safe because, although the type of x-65536
could be long
, its value fits in an int
—unless you are executing in a C implementation that limits int
to −32767 to +32767, and the original value may be −32768, in which case you should stick to the first option.
Upvotes: 1
Reputation: 108978
#include <inttypes.h>
uint16_t foo = -75;
printf("==> %" PRId16 " <==\n", foo); // type mismatch, undefined behavior
Upvotes: 1
Reputation: 51
Go ahead with the union, as explained by another answer. Just wanted to say that if you are using GCC, there's a very cool feature that allows you to do that sort of "bitwise" casting without writing much code:
printf("%d", ((union {uint16_t in; int16_t out}) foo).out);
See https://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Cast-to-Union.html.
Upvotes: 0
Reputation: 21532
If an int
is 32 bits on your system, then the correct format for printing a 16-bit int is %hu
for unsigned and %hd
for signed.
Examine the output of:
uint16_t n = (uint16_t)-75;
printf("%d\n", (int)n); // Output: 65461
printf("%hu\n", n); // Output: 65461
printf("%hd\n", n); // Output: -75
Upvotes: 1