How does the compiler work in the case of a casting like this?

1

Having the following code:

0    #include<stdio.h>
1    
2    int
3    main(void)
4    {
5        int x;
6        x = -3;
7        
8        for (int i = 0; i < 5; i++)
9        {
10          printf("%d\n", (unsigned int) (x - i)); //necessita mesmo de parêntesis aq?
11          printf("%u\n", (int) (x - i));       //necessita mesmo de parêntesis aqui?
12      
13          printf("%d\n", x - i);
14          printf("%u\n\n", x - i);
15       }
16 
17        return 0;
18    }

To compile I used: gcc -Wall -pedantic -std=c99 -o test.exe test.c

The output of the code above was as follows:

-3
4294967293
-3
4294967293

-4
4294967292
-4
4294967292

-5
4294967291
-5
4294967291

-6
4294967290
-6
4294967290

-7
4294967289
-7
4294967289

Doubt 1) On lines 10 and 11 the compiler temporarily converts the types to the given casting type and then converts implicitly to %d and %u types or simply ignores casting and formats directly according to the specifier formatting?

Doubt 2) The unsigned int converts a signed int to an unsigned int . But anyway, how does the compiler do this? Note that the above code outputs when printing a negative integer by formatting it to unsigned int (in the case of code above, implicitly in lines 11 and 14) the output is an integer value (different from the desired one) that decreases proportionally to the value wanted. Why does this occur?

    
asked by anonymous 31.08.2014 / 02:43

2 answers

1

When you call printf passing two arguments - a string and a number - there is no way for the compiler to know what printf will do with them; pro compiler, is a normal function call. So he can not ignore casting - he converts the type first, and then passes it as a parameter to the function. The fact that this function is converted back later is irrelevant.

As for the form of conversion, what the compiler does is simply take the data in binary - without any modification - and interpret it in a different way. Here are some examples:

Sequência de bits                     Inteiro com sinal   Inteiro sem sinal
===========================================================================
00000000 00000000 00000000 00000010            2                   2
00000000 00000000 00000000 00000001            1                   1
00000000 00000000 00000000 00000000            0                   0
11111111 11111111 11111111 11111111           -1          4294967295
11111111 11111111 11111111 11111110           -2          4294967294
11111111 11111111 11111111 11111101           -3          4294967293

That is, when you have an integer variable with a signal, with the value -3 , internally it is represented by the bit sequence shown in the last line. This same string, interpreted as an unsigned integer, corresponds to the value shown in the last column.

Finally, a comment regarding whether to use parentheses in cast : I do not know if it is necessary or not, but I always use it even if it is to make it clear to the code reader my intention (even if this reader is myself, after months without touching the program). That is, one of these two is unnecessary:

(unsigned int) (x - i)
((unsigned int)x) - i

I do not know what it is, and I'm not interested in knowing ... I do it and that's it!

    
31.08.2014 / 04:45
3

Of your four printf only 1 is correct. The other three do Undefined Behavior

   printf("%d\n", (unsigned int) (x - i)); // UB
   printf("%u\n", (int) (x - i));          // UB
   printf("%d\n", x - i);                  //
   printf("%u\n\n", x - i);                // UB

The submitted value type must match the specified conversion format.

In the first% specifc% printf that requires a value of type "%d" ; but you type a value of type int . In the second% specifc% unsigned int that requires a value of type printf ; but you type a value of type "%u" . In the third% specified unsigned % requires a value of type int ; and, correctly, you send a value of type printf . In the room "%d" specifies int which requires a value of type int ; but you're sending a value of type printf .

    
31.08.2014 / 12:11