0

As you can see in the program, The first output is 6356744 and the second output is 0060FF08, why is it different? Is the %d typecasting it into an integer, if so, how?

#include<stdio.h>
int main()

{

    int *a;
    int b = 7;
    a = &b;
    printf(" The value of a = %d",a);
    printf("\n The value of a= %p",a);

}
phuclv
  • 37,963
  • 15
  • 156
  • 475

4 Answers4

1

Printing a pointer with %d is formally undefined behavior, meaning anything can happen, including a program crash. Your program will for example likely break when you compile it as a 64 bit application, where int is 32 bits but a pointer is likely 64 bits. Therefore, always use %p and never anything else when printing a pointer.

There is no implicit conversion taking place - the printf family of functions doesn't have that kind of intelligence - it doesn't know the type passed. With the format specifier, you tell the function which type it is getting. And if you lie to printf and say "I'll give you an int" and then give it a pointer, you unleash bugs. This makes the printf family of functions very dangerous in general.

(The only implicit conversion that take place in printf is when you pass small integer types or float, in which case the "default argument promotions" take place and promote the parameter either to int or double. This is not the case here, however.)

In this specific case, you happened to get the decimal representation of 0x0060FF08, which is by no means guaranteed.

Pedantically, you should also cast the pointer to type (void*) since this is what %p expects.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • "_The only implicit conversion that take place in printf ..._" That formally is not a conversion by printf but by C in general (argument promotion). – Paul Ogilvie Apr 16 '18 at 15:07
  • @PaulOgilvie The default argument promotions are invoked for all variable argument list functions, printf being no exception. C11 6.5.2.2/7. – Lundin Apr 16 '18 at 15:08
  • So it is not an implicit conversion of _printf_, which is my point. – Paul Ogilvie Apr 16 '18 at 15:12
  • Further to your comment reply, does the promotions only take place for variable argument lists? I thought they are for arguments of all functions. – Paul Ogilvie Apr 16 '18 at 15:14
  • @PaulOgilvie You still get them if you do something smelly, such as not using proper function prototype format. – Lundin Apr 16 '18 at 15:20
  • Hmmm...C11 6.5.2.2.6 and 7 are a bit hard to read. Seems there is no promotion when there is a complete prototype (but how to pass small int if not promoted to full int on e.g. x86, or how to pass a single char? Maybe that is not called "promotion" but part of the ABI) – Paul Ogilvie Apr 16 '18 at 15:25
  • @PaulOgilvie §7 is regarding a properly prototyped variadic function, the relevant part being "The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments." Meaning that if you have `void foo (char x, ...)`, then `x` is not default argument promoted, but the rest of the arguments are. – Lundin Apr 16 '18 at 15:28
  • and how e.g. `char` is passed is platform/compiler dependent. On x86 it will be placed in an object that can be pushed onto the stack, this object probably being wider than the char, but that is not promotion but ABI. Think I get it; thx. – Paul Ogilvie Apr 16 '18 at 15:34
0

%p prints a pointer and it's not necessarily hexadecimal, or even a number

Elarbi Mohamed Aymen
  • 1,617
  • 2
  • 14
  • 26
0

If format specifiers do not match the datatype of the provided parameter, you yield undefined behaviour. %d expects an integral value, such that when you pass a pointer value, you get undefined behaviour (cf., for example, cppreference.com-printf):

...If any argument after default argument promotions is not the type expected by the corresponding conversion specifier, or if there are fewer arguments than required by format, the behavior is undefined.

The (only) correct format specifier for printing pointer values is %p, usually printing the address in hex format.

One of the undefined behaviours is that %d takes the pointer value as an 32/64 bit integral value and hence prints decimals, which - if you printed it using the correct %p-format - corresponds to the hex-value of the address (yet in decimal format).

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
0

%d prints an int, in decimal.

%p prints a pointer (strictly speaking, a void * pointer) in an implementation-defined way, typically in hexadecimal.

On a machine where ints and pointers have different sizes, trying to print a pointer using %d will typically give a meaningless result. For example, on a lot of machines these days, ints are 32 bits while pointers are 64 bits. So if you try to print a pointer using %d, what you might get is half the pointer value, in decimal.

(Strictly speaking, trying to print a pointer using %d is undefined, no matter what the relative sizes are.)

Bottom line, use the right printf specifier for the job. Use %d to print ints. Use %p to print pointers. Don't try to mix 'n' match.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103