Tuesday, April 12, 2022

[SOLVED] printing uint8_t (char) with "%d" without casting takes the MSB and not the LSB?

Issue

let's take the following code:

#include <stdio.h>
#include <inttypes.h>

typedef enum
{
  BLAH = 9,
}fiz_e;

int main(void)
{
    fiz_e foo = BLAH;
    uint32_t bar = 9;

    printf("foo d %d x 0x%08x\n",(int)foo,(unsigned int)foo);

    if (bar == foo) printf("Hi\n");

    if (bar == (uint32_t)foo) printf("Ho\n");
    
    return 0;
}

Intuitively I would have said that this program displays:

foo d 9 x 0x00000009
Hi
Ho

BTW, this is also what I got when I compiled it on every online compiler I tried.

However, I'm (cross) compiling on a pulpino with riscv toolchain (riscv32-unknown-elf-gcc, gcc version 5.2.0), and I got the following result:

foo d 0 x 0x00000009
Ho

as if when not casting to uint32_t, it would take the msb and not truncate it...

Does endianness could explain this?

What does the standard say about this?


Solution

Intuitively I would have said that this program displays:

foo d 9 x 0x00000009
Hi
Ho

Analytically, I would say that, too.

I got the following result:

foo d 0 x 0x00000009
Ho

as if when not casting to uint32_t, it would take the msb and not truncate it...

C doesn't work that way.

Does endianness could explain this?

No. The behaviors of arithmetic, comparison, and typecast operators are defined in terms of the value, not representation, of their operand(s), and it is the value of the result that is specified, not its representation.

What does the standard say about this?

Summarizing some of the relevant implications of the standard that have not already been covered:

  • enum types, such as your fiz_e, are integer types.
  • All conversions, including those produced by typecast operators, are value-preserving when the value being converted is representable by the target data type.
  • All of int, unsigned int, uint32_t (provided the implementation defines it), and your fiz_e can represent the value 9.
  • int and unsigned int are not affected by the integer promotions, so there are no additional conversions performed on the arguments to your printf call.
  • overall, the behavior you describe for the cross-compiled binary does not conform to the language specification.

Insufficient information is given to say what's wrong with your toolchain or execution environment, or with details of your usage of those, that produces the non-conforming behavior you describe.



Answered By - John Bollinger
Answer Checked By - Clifford M. (WPSolving Volunteer)