1

I need to make a signed value into an unsigned value and while trying to get this to work I found uint32_t is somehow signed when i assign the MSB to 1.

In this code i show what i mean. Test1/2 are to show this isn't only a printf problem, but arimethics aswell.

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

     void main() {
        int reg1S = 0xfffffff4;
        int reg2S = 0xfffffff2;
              
        uint32_t reg1U = 0xfffffff4;
        uint32_t reg2U = 0xfffffff2;

        uint8_t test1,test2;

        test1 = (reg1S < reg2S ? 1:0);                      
        test2 = (reg1U < reg2U ? 1:0); 

        printf("signed = %d \t",test1);
        printf("unsigned = %d \n", test2);
        printf("reg1S= %d \t", reg1S);
        printf("reg1U= %d \n", reg1U);
        printf("reg2S= %d \t", reg2S);
        printf("reg2U= %d \n", reg2U);
     }

this is what the code outputs

signed = 0  unsigned = 0 
reg1S= -12  reg1U= -12 
reg2S= -14  reg2U= -14

note: it doesnt do this with 8 or 16 bit unsigned ints, only 32 and 64 bit

  • 2
    You are using a wrong format specifier for `uint32_t`. See https://stackoverflow.com/questions/3168275/printf-format-specifiers-for-uint32-t-and-size-t – Eugene Sh. Nov 25 '21 at 21:29
  • `printf()` doesn't know or care what data was passed to it (or even if there was none passed). If you tell it `%d` then it will look where it expects the data to be and interpret it as if it is `int` type, no matter what is passed. If a floating point variable was passed, unlike normal functions there is no type conversion (apart from type promotions) and again `printf()` looks at 32-bit data and assumes it is `int` data. – Weather Vane Nov 25 '21 at 21:39

2 Answers2

4

%d is for printing signed types. To print unsigned types, use %u.

Also, types smaller than int will be promoted to that type when passed to printf which is why you don't see this behavior with those types.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 2
    There could be a pathological case where `unsigned int` is smaller than `uint32_t`. Then this won't work. There is a "proper" format specifier `"%"PRIu32` for this – Eugene Sh. Nov 25 '21 at 21:32
  • thanks this explains the printf problem. But it doesnt explain why it says ffffff4 is lower than fffffff2 – Magnus Mikkelsen Nov 25 '21 at 21:36
  • Because `-14` is smaller then `-12` – KamilCuk Nov 25 '21 at 21:38
  • @MagnusMikkelsen `0xfffffff4` is unsigned and does not fit into a signed `int`. So it is being converted with implementation-defined result (as per http://port70.net/~nsz/c/c11/n1570.html#6.3.1.3p3). In your case it is most likely interpreting the bit patter as 2's complement represented negative number. – Eugene Sh. Nov 25 '21 at 21:38
  • test2 uses unsigned integers so that should give me back 1 as 0xfffffff4 is higher than fffffff2 – Magnus Mikkelsen Nov 25 '21 at 22:58
1

Use the correct formats for fixed size integers:

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

 void main() {
    int32_t reg1S = 0xfffffff4; \\ <- implementation defined
    int32_t reg2S = 0xfffffff2; \\ <- implementation defined
          
    uint32_t reg1U = 0xfffffff4;
    uint32_t reg2U = 0xfffffff2;

    printf("reg1S= %"PRIi32" \t", reg1S);
    printf("reg1U= %"PRIu32" \n", reg1U);
    printf("reg2S= %"PRIi32" \t", reg2S);
    printf("reg2U= %"PRIu32" \n", reg2U);
 }
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
0___________
  • 60,014
  • 4
  • 34
  • 74