2
#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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

3 Answers3

5

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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

%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.

CoffeeTableEspresso
  • 2,614
  • 1
  • 12
  • 30
  • The Standard requires that values from 0 to INT_MAX have the same bit-level representations in signed and unsigned types. I think the authors deliberately *waived judgment* as to what this should imply about the behavior of printf format lists, since it is sometimes be useful to have implementations issue diagnostics related to constructs that could be processed predictably, but are likely to be erroneous, based on criteria not recognized by the Standard. For example, `printf("%02X", signedChar);` is much more likely to behave in undesired fashion than `printf("%02X", unsigedChar);`, but... – supercat Jul 11 '22 at 15:54
  • ...both arguments would on most platforms be converted to type `signed int`, so as far as the Standard is concerned, there's no reason an implementation should silently accept the latter but not the first. – supercat Jul 11 '22 at 15:55
1

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.

  • 2
    "%d will always have bit 1 set at the top of register data ..." --> this is all implementation dependent, not an _always_. – chux - Reinstate Monica Jul 08 '22 at 19:54
  • *Well of course "%u\n" has different address than "%d\n" because these are different values created one after another.* The question is printing the address of `a`, not the address of the string literal used as the format string. – Andrew Henle Jul 08 '22 at 19:56
  • @AndrewHenle You are right. "So My Question is what difference between two format specifier?". The whole question is about what my answer is about but it's out of context. Still useful tho. – rafineria888wp Jul 08 '22 at 20:03
  • I updated the answer. For the the real answer is inside the source code of `printf`. – rafineria888wp Jul 08 '22 at 20:18