Home > Net >  Format Specifier: %u vs %d in C
Format Specifier: %u vs %d in C

Time:07-09

#include<stdio.h>

int main(){
    int a = 3;
    printf("%u\n",&a);
    printf("%d\n",&a);
    return 0;
}

I was trying to print address of Variable, "a". Now with usage of two different format specifier, "%u" and "%d", two different memory address is printed which I find it wierd.

So My Question is what difference between two format specifier?

CodePudding user response:

Using the both conversion specifiers to output an address invokes undefined behavior.

From the C Standard (7.21.6.1 The fprintf function)

9 If a conversion specification is invalid, the behavior is undefined.275) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Instead you should use the conversion specifier p as for example

printf( "%p\n", ( void * )&a );

Another approach is to use integer types intptr_t or uintptr_t declared in the header <stdint.h> and to use specifiers PRIdPTR or PRIuPTR or, for example, PRIxPTR declared in the header <inttypes.h> to output assigned values of pointers of the type void *.

Here is a demonstration program.

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

int main( void )
{
    int a = 3;
    intptr_t p1 = ( intptr_t )( void * )&a;
    uintptr_t p2 = ( uintptr_t )( void * )&a;

    printf( "&a = %p\n", ( void * )&a );
    printf( "&a = %"PRIdPTR "\n", p1 );
    printf( "&a = %"PRIuPTR "\n", p2 );
    printf( "&a = %#"PRIxPTR "\n", p2 );
}

The program output is

&a = 0x7ffc220b16ec
&a = 140720879638252
&a = 140720879638252
&a = 0x7ffc220b16ec

CodePudding user response:

%d is for signed integers, %u is for unsigned integers.

So, when you print the same value out with %d and with %u, you may get different values, since the bytes you're printing out are being interpreted differently. (Once as a signed integer, once as an unsigned integer.)

Final note, you should use %p ("p" for "pointer") to print out addresses.

CodePudding user response:

Well of course "%u\n" has different address than "%d\n" because these are different values created one after another. Look at ASM:

enter image description here

RDX register will have the same value for both printf calls because of LEA instruction is putting the same address into it.

But what you probably see are the values of RCX register which contains different printf format value address for each printf call.

Now the answer:

%d is signed decimal integer.

%u is unsigned decimal integer.

The problem occurs when there is a printf call. This function changes the value of RDX register which is the memory address of a variable.

  • Related