Im confused regarding %p specifier [duplicate] - c

This question already has answers here:
Difference between %d and %p printf format string directives in c language?
(3 answers)
Closed 5 years ago.
#include <stdio.h>
int main(void)
{
int i=10;
printf("%p",i);
return 0;
}
output:-
0xa
%p - I have read %p is used to print pointer in printf, but here i is an integer,and also there is no pointer declared so how "0xa" gets output.

The behaviour of your code is undefined since an %p is not an appropriate format specifier for an int type.
The compiler is allowed to do anything, which includes optimising your code to int main(){}.

Technically it is undefined behaviour because %p is the wrong format specifier for an int.
But if your platform is 32 bits, then %p usually boils down to printing the supplied value in hexadecimal on most implementations and therefore printf("%p", 10); will usually print 0xA or 0x0000000A on these implementations.
Anyway, don't use unmatched format specifiers, because even if it appears to work, it results in undefined behaviour.

Related

Why does %d,and %p give different values? [duplicate]

This question already has answers here:
What happens when I use the wrong format specifier?
(2 answers)
Correct format specifier to print pointer or address?
(5 answers)
Closed 4 years ago.
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);
}
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.
%p prints a pointer and it's not necessarily hexadecimal, or even a number
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).
%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.

How can a variable have two different addresses at same point of time? [duplicate]

This question already has answers here:
How to printf a memory address in C
(2 answers)
Closed 5 years ago.
I tried to play around a little bit with pointer for some assigned value of 'i' and what I found out in in that there are two different addresses assigned for declaration %u and %lu,%llu. How is possible that a variable can have two different addresses at the same instance of execution -
#include <stdio.h>
int main(void)
{
int i;
float f;
printf("\nEnter an integer:\t");
scanf("%d",&i);
printf("\nValue of address of i=%u",&i);
printf("\nvalue of address of i=%d",&i);
printf("\nValue of address of i=%lu",&i);
printf("\nValue of address of i=%llu",&i);
printf("\nvalue of i=%d",i);
printf("\nvalue of i=%u",i);
printf("\nvalue of i=%lu",i);
printf("\nvalue of i=%llu\n",i);
}
This is the output -
aalpanigrahi#aalpanigrahi-HP-Pavilion-g4-Notebook-PC:~/Desktop/Daily programs/pointers$ ./pointer001
Enter an integer: 12
Value of address of i=1193639268
value of address of i=1193639268
Value of address of i=140725797092708
Value of address of i=140725797092708
value of i=12
value of i=12
value of i=12
value of i=12
Here we can clearly see that for %u and %d the address is 1193639268 (Though the output of %d and %u might not be equal in all cases) and the output of %lu and %llu is 140725797092708 and what is it's physical significance.
The proper format specifier for printing a pointer is %p.
Using the wrong format specifier, such as %d, %u, %lu, or %llu invokes undefined behavior.
As the the specific behavior you're seeing, a pointer on your particular implementation is probably an 8 byte value, while an int or unsigned int is probably a 4 byte value. As a result, using %d or %u only reads the first 4 bytes of the 8 byte value passed in to the function and prints that value. When you then use %lu or %llu, all 8 bytes are read and printed as such.
Again, because you're invoking undefined behavior, you can't depend on this particular output to be consistent. For example, compiling in 32-bit mode vs 64-bit mode will likely give different results. Best to use %p, and also to cast the pointer to void *, as that is the specific pointer type expected by %p.
There is only one address. You're using integer printing codes of varying widths, so sometimes you see 32 bits of address, and sometimes you see 64 bits of address. How much is valid depends on your system; on a 32 bit system, printing 64 bits means 32 bits of the value are garbage; on a 64 bit system, printing 32 bits means you're omitting half the pointer.
There is a dedicated format code, %p that's intended for printing pointers, use that, not integer printing codes.
You're using the wrong format specifier, which results in undefined behavior. In this specific case the behavior is that 1193639268 (0x47257D64) is the lower part of 140725797092708 (0x7FFD47257D64)
The correct format specifier for addresses is %p
It doesn't. It's just that you are using incorrect format specifiers for pointer types.
The behaviour on doing that is undefined. The output you observe is a manifestation of that undefined behaviour.
Use %p for a pointer, and cast the pointer argument to a const void* type (many compilers are lax on this last point but it's good practice nonetheless).

What exactly is %p and why is it different from printing the int value of pointer by using %d? [duplicate]

This question already has answers here:
What happens when I use the wrong format specifier?
(2 answers)
Closed 6 years ago.
#include <stdio.h>
int main()
{
int *ptr;
int a=2;
ptr=&a;
printf("%p\n",ptr);
printf("%d\n",ptr);
printf("%p\n",a);
return 0;
}
The output I get is:
% ./a.out
0x7ffe12032c40
302197824
0x2
%
The value of the first two output changes (obviously because of ASLR) and the 0x2 remains constant.
The size of pointer isn't equal size of int, So you can't use %d instead of %p, %p is used for printing value stored in pointer variable, also using %p with int variable is undefined behavior (if you're on system which pointer and int have same size you may see correct result, but as C standard its an undefined behavior )
sizeof int is defined by compiler, different compilers may have different size of int on single machine, but pointer size is defined by machine type (8,16,32,64 bit)
0x2 is simply the hex representation of integer 2.
That is why you see that output
printf() prints the value of variable a in hex format. If you want to print the address of a, do the following
printf("%p",&a);
When you use %p as in
printf("%p\n",ptr);
%p is the format specifier for pointers, you get the expected results
When you use %d as in
printf("%d\n",ptr);
%d is the format specifier for signed integers, you get unexpected results because the size of pointers (which is usually 8 bytes) can be different from size of signed integers(which is usually 4 bytes).
It is for printing pointers. In the same way you don't print a float with %d you should not be printing a pointer with %d.

how does printf %n count characters? [duplicate]

This question already has answers here:
What is the use of the %n format specifier in C?
(12 answers)
Closed 7 years ago.
#include <stdio.h>
int main()
{
int val;
printf("blah%p%nblah", &val, &val);
printf("val = %d\n", val);
return 0;
}
This demo program is complied on 32-bit machine. I think val should be 8.
But I got this:
$ ./a.out
blah0xffa9b6fcblahval = 14
Why 14? blah is 4 chars. A pointer in IA32 should be 4 bytes. %n prints nothing.
Please count the number of printed characters, they are 14.
The value stored in the variable int pointer the "%n" specifier is the number of characters printed prior to the occurrance of the "%n" specifier, there are 10 for the poitner address and 4 for blah.
blah0xffa9b6fc /* these are exactly 14 characters
^ ^
%s %p
*/
Just to support what Mr. Iharob said in his answer,
Quoting from C11, chapter ยง7.21.6.1, fprintf(), (emphasis mine)
n
The argument shall be a pointer to signed integer into which is written the
number of characters written to the output stream so far by this call to
fprintf. No argument is converted, but one is consumed. If the conversion
specification includes any flags, a field width, or a precision, the behavior is
undefined.
So, it does not count the bytes in format string, rather, the actual printed bytes.
That said, the recommended signature of main() is int main(void).
This output string (before format specifier %n will be encountered)
blah0xffa9b6fc
contains exactly 14 symbols. The reason for val contains 14 is that format specifier %p outputs addresses in the hexadecimal notation
0xffa9b6fc
And indeed in your platform pointers have size of 4 bytes.:)

printf function in c [duplicate]

This question already has answers here:
float to int unexpected behaviour
(6 answers)
Closed 6 years ago.
here are part of my code.
float a = 12.5;
printf("%d\n", a);
printf("%d\n", (int)a);
printf("%d\n", *(int *)&a);
when I compile in windows, I got:
0
12
1094713344
and then, I compile in linux, I got:
-1437851864
12
1094713344
-1437851864 will be changed every time I excuted it.
my question is: in how does the "printf" function works in linux
It works very well, but why are you passing the wrong sort of data to it? The %d specifier expects and int, but you're passing something else. Bad idea.
If float and int are differently sized across the varargs barrier, this is undefined behavior. And since float is typically promoted to double with varargs calls, if your int is smaller than your double this will break.
In short, this is really bad and broken code. Don't do this.
To print a floating point number in C, you should do:
float a = 12.5;
printf("%f\n", a);
As has been mentioned, passing arguments with types not matching the format string invokes undefined behaviour, so the language standard doesn't place any restrictions on what
float a = 12.5;
printf("%d\n", a);
actually does.
To find out what it does, you'd need to analyse your implementation, or at least the assembly the compiler produced for that code.
A common way for translating that code is to pass the promoted (to double) float argument in a floating point register and tell printf how many arguments are passed in floating point registers. But since the format tells printf to look for an int, it doesn't look in a floating point register for it, but in another register. So the printed value would be whatever happened to be in that register when printf was called.

Resources