2

I was trying to work on something and I basically have two questions. When creating a signed char, how do you a) what is the convention of initialization and print statement used to print it in hexadecimal and b) if I have a value of -32 assigned to my char, how do I print the hex without the 'ffffff' before the 'e0' and only print the 'e0'(without removing the - if it's possible)

I have tried all the regular syntax that is given, just wondering if it's something obvious that I am missing.

#include <stdio.h>

int main(void) {
    signed char tempC = -32;
    printf("%x\n", tempC);
    return 0;
}

Expected result: e0

Actual result: ffffffe0

Trideep
  • 51
  • 8
  • 1
    The `%x` format specifies that the corresponding argument is of type `unsigned`. By passing a `signed char`, the behaviour of your code is therefore undefined. To do what you expect, you need to convert the `signed char` to `unsigned char`, then convert that `unsigned char` to `unsigned` in order to print. For example, `printf("%x\n", (unsigned)((unsigned char)tempC))`. And, no, you can't jsut convert it directly to `unsigned`, as conversion of `signed char` to `unsigned` will wrap based on the maximum value of an `unsigned`. – Peter Aug 17 '19 at 04:47
  • If you want to use `%x` in your `printf` format, then you need to pass it an `unsigned int`. You can use `(unsigned) (tempC & 0xff)`. In this context, `tempC` is promoted to `signed int`, then everything but the rightmost 8 bits is masked off, and the result is cast to `unsigned int`. – Tom Karzes Aug 17 '19 at 04:50
  • @Peter why do you say `unsigned` not `signed`? Both `-32` and `0xff` can be represented as `int` so according to [C11 Standard - 6.3.1.1 Boolean, characters, and integers(p2)](http://port70.net/~nsz/c/c11/n1570.html#6.3.1.1p2) the promotion is to `int`. – David C. Rankin Aug 17 '19 at 05:06

2 Answers2

2

Well, that's how signed numbers are represented.

It's the 2's complement form.

If you take it as:

unsigned char tempC = -32;

it would result into e0.

The simple logic is that %x format specifier would print all 32 bits whereas char just has 8 bits. Remaining 24 bits are 1 because they were stored in 2's complement form. As you would know 1111 represents f in hexadecimal. So ffffff would represent those remaining 24 bits

In case of unsigned char, they are not stored as 2's complement, remaining 24 bits are 0.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mihir Luthra
  • 6,059
  • 3
  • 14
  • 39
2

The arguments for the ellipsis portion of a variable-arguments function such as printf() undergo default argument promotions (C11 §6.5.2.2 Function calls, ¶6). That means a signed char is converted to signed int. You then attempt to print that as a hexadecimal value. That strictly leads to undefined behaviour (the value being printed is not representable as both int and unsigned int and hexadecimal formatting assumes unsigned int), but you usually get what you see.

You could use %hhx to print the value as (unsigned) char if your system supports C99 format strings. You could trim the value passed with tempC & 0xFF.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I suspect `"%hhx"` is still UB. Format expects an `unsigned` argument and `-32` as a promoted `int` fails the "not representable as both int and unsigned int". – chux - Reinstate Monica Aug 17 '19 at 15:12