Alternative for "%p" format specifier - c

I'm using a platform/compiler on an embedded system (specifically, XC8 on a PIC) that does not include the %p pointer address format specifier for printf().
For example:
printf("J: %f [# 0x%p]\r\n", j, &j);
Would display the value and address of a variable called "j" with most compilers. However, according to the compiler documentation it does not include support for %p. Giving the error "invalid format specifier or type modifier".
So in that case, what is an alternative to printing the variable's address?

Nominally, you would use the <inttypes.h> header, the uintptr_t type, and the PRIXPTR or PRIxPTR format (first formally defined in C99 or ISO/IEC 9899:1999):
printf("J: %f [# 0x%" PRIXPTR "]\r\n", j, (uintptr_t)&j);
However, if you don't have %p, you probably don't have those either, so you are likely to have to fall back on:
printf("J: %f [# 0x%lX]\r\n", j, (unsigned long)&j);
This assumes sizeof(unsigned long) == sizeof(void *); if not, you need to use an integer type such that the sizeof(other_integer_type) == sizeof(void *). You'll need to explain in detail the types on your machine if you can't find such a type.

The %p format is normally implemented by the printf function in the runtime library, not in the compiler. The distinction can be important for implementations where the compiler and library don't necessarily come from the same vendor or other source. (Some compilers may optimize printf calls with literal format strings; thanks to chux for pointing this out.)
As Matt McNabb's comment suggests, you can very probably convert the pointer to unsigned long and use %lx to print it. I'd probably use something like:
printf("J: %f [# 0x%lx]\r\n", j, (unsigned long)&j);
It's possible this could fail if (a) pointers are wider than unsigned long or (b) the conversion from a pointer type to unsigned long loses information. I've worked on some odd systems, but I've never seen one that would violate either of these assumptions.
Since your code probably isn't meant to be portable anyway, you can check the sizes of pointers and unsigned long on your platform. If you're feeling paranoid, you can add something like:
assert(sizeof (unsigned long) >= sizeof (void*));
just to be (almost) sure that the conversion won't lose information.

Related

Make 7 year ago prints compatible with now

I'm reading the book The Art Of Exploitation and there is a program called memory_segments.c which just demostrante to us how the memory segments works, the heap, the stack and etc. But when I try to compile the program it seems like that the printing isn't more compatible with now. I use gcc 10.2.0 to compile my C code.
#include <stdio.h>
#include <stdlib.h>
int global_initialized_var = 5;
int main()
{
printf("global_initialized_var is at address 0x%08x\n", &global_initialized_var);
// ... more prints, removed just to make code shorter
return 0;
}
// warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’
The author of the book's output:
...
global_initialized_var is at address 0x080497ec
...
What is the alternative for 0x%08x? And why does 0x%08x no longer work?
%x prints integer values not pointers. It is Undefined Behaviour. To print pointers use printf("%p", (void *)pointer);
The integer types which should be used when converting pointers are uintptr_t or intptr_t. For differences between pointers ptrdiff_t
To print uintptr_t or intptr_t you need to use PRIdPTR PRIiPTR PRIoPTR PRIuPTR PRIxPTR PRIXPTR printf formats. Example:
uintptr_t p = SOME_VALUE;
printf("UINTPTR_T printed as hex: %" PRIxPTR "\n", p);
What is the alternative for 0x%08x?
To properly print a pointer value, use %p with void* pointer:
printf("%p\n", (void*)&global_initialized_var);
It will use some implementation-specific form of printing it, most commonly it's the same as %#x format. If you want to get a specific numeric representation of the pointer, the best standard way would be to use the biggest possible integer type:
printf("%#jx\n", (uintmax_t)(uintptr_t)&global_initialized_var);
However, usually you can/want to just cast the pointer value to an integer and print it, as usually it's only for temporary debugging purposes, just like:
// Could truncate pointer value!
printf("%#llx\n", (unsigned long long)&global_initialized_var);
printf("%#lx\n", (unsigned long)&global_initialized_var);
printf("%#x\n", (unsigned)&global_initialized_var);
Note that unsigned has at least 16 bits, long has at least 32-bits and long long has at least 64-bits. Platforms are nowadays 64-bit, pointers are 64-bit - anyway, prefer the widest available type when printing pointer value, to be portable - thus the use uintmax_t above. It was common on unix platforms to use long to cast to/from pointers - on 64-bit unix long has 64-bits, while on windows it has 32-bits.
why does 0x%08x no longer work?
It is (and was) UB due to mis-matched types.
%x expects an unsigned. &global_initialized_var is a pointer.

How to print the address value of a pointer in a C program?

I'm trying to learn how to use the pointer in a C program; my example is as follows:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int * tab = (int*)malloc(sizeof(int)*5);
int a = 10;
int *p;
p = &a;
printf("the address of a is %d \n",&a);
printf("the address of a using the pointer is %p \n",p);
printf("the address of tab is %d \n",tab);
}
I'm trying to print the address of a, the address value inside of p and where the first byte of the tab begins.
I can get hexadecimal values when using "%p", but I'm willing the decimal value of the addresses.
Edit : On this Video image, someone has used "%d" to print a decimal value for a pointer address, and it has confused me.
To print a decimal version of an object pointer, 1st convert the pointer to an integer. Best to use the optional type uintptr_t.
The following type (uintptr_t) designates an unsigned integer type with the property that any valid pointer to void can be converted to this type (uintptr_t) ... C11dr §7.20.1.4 1
#include <inttypes.h>
uintptr_t d = (uintptr_t)(void *) &a;
Then print it.
Some info on PRIuPTR
printf("%" PRIuPTR "\n", d);
For pre-C99 code, consider a direct cast to unsigned long. #Barmar
OP later commented
"... i will try to manipulate the tab variable , and i will test if every cell in the tab is 4 byte , so may be i will do tab+8 bytes to get the value of a specific cell , here it's a simple example , with decimal it will be easy for me ."
This is a questionable approach as the decimalization of a pointer may not provide the continuous numeric model expected. This post this may be good for learning, but with OP providing more details in another post, even better ideas could be given for the higher level problem.
First, be aware that addresses are often "number-like" but might not be (e.g. remember the segment+offset notion of far addresses on 1980-era 16 bits x86 PCs).
Then, the integral type the most similar to pointers is intptr_t (signed) or uintptr_t (unsigned) - both from <stdint.h>.
You might cast that to a long long (hoping that they are not smaller than pointers), e.g.
printf("address of a in decimal is %lld\n", (long long) (intptr_t) (&a));
But really, why do you want to show an address in such a fashion? I see no need for it (e.g. debuggers or linkers are generally showing addresses in hexa, which is probably what %p does).
Notice that the C11 standard (see n1570, §7.21.6.2, p315) does not say much about %p for printing pointer:
The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
I'm understanding the above in a way where printing Hello ⭔ for any pointer would be an acceptable and standard conforming behavior. In practice, implementations print pointers in a way similar to what linkers and debuggers do, and don't behave in a silly way (but I understand they could).
At last, the actual concrete "numerical" value of a pointer is not really important and can vary greatly from one execution to the next (e.g. because of ASLR).
For printing an "address" (actually a pointer) "%p" is the most common method (note the necessary cast to void*). If you need the address in decimal instead of hexadecimal, you can convert the pointer into an integral value; this is well defined in C (cf. this online C standard draft):
6.3.2.3 Pointers
(6) Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
So the code could look as follows:
int main(int argc, char *argv[]) {
int a =10;
int *p = &a;
p = &a;
unsigned long long addrAsInt = (unsigned long long)p;
printf("the adress of a is %llu \n",addrAsInt);
printf("the adress of a using the pointer is %p \n",(void*)p);
}
If you want to see the pointer as a decimal integer, cast it to unsigned long and print it with %lu format. While this isn't guaranteed by the standard, it should work in most implementations.
printf("the address of a is %lu\n", (unsigned long)&a);

When printing a memory address of a variable using printf, why do %x and %p return different yet similar values?

I am trying to print the memory address of a variable (specifically argc). I am using printf and I know that %x returns an unsigned hexadecimal integer and %p returns a pointer address. My simple code is below for reference
int main (int argc, char **argv) {
printf("argc: addr=%x addrp=%p val=%x\n",&argc,&argc,argc);
return 0;
}
Ran like so: ./a.out this is
It outputs: argc: addr=af5144cc addrp=0x7ffcaf5144cc val=3
I see that the %x returns what is the address of a byte, correct? Since it has 8 digits or bits?
However, %p returns what is the same byte with more info before it. What is the "0x7ffc" part and what does it mean? Is it part of the memory address or does it point out some type of information? I know the 0x part means it is a hexadecimal number. Is %x or %p the true memory address? Thanks!
%x prints an unsigned int, which on most modern platforms, is 32-bits.
%p prints a platform-specific pointer value.
Some platforms are 32-bit, some are 64-bit (there may be other sizes too)
sizeof(unsigned int) is often equal to sizeof(void*), but it is not guaranteed at all, and it is common to see 32-bit unsigned int with 64-bit void*.
As a result, %x and %p print different widths.
The code is invoking undefined behavior. The fprintf specification from the C Standard is stating (the emphasis is mine):
For %x
o,u,x,X
-- The unsigned int argument is converted to unsigned octal (o), unsigned decimal
(u), or unsigned hexadecimal notation (x or X) in the style dddd;
And for %p:
p
The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.
And then here:
If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined.
You are feeding both specifiers it with a non-void pointers, which are definitely not the correct type for the conversion specification.
Update
As suggested by #chux the fully compliant call will look as following:
printf("argc: addr=%x addrp=%p val=%x\n",
(unsigned)(uintptr_t)(void*) &argc, (void*)&argc, (unsigned)argc);
Because pointers are not integers.
Pointers are pointers. The right way to printf a pointer is using %p.
You might think you know that pointers are just integers. (Back in the day, pointers were just integers.) If you know what you're doing, you can still probably get away with treating pointers as integers, but you have to know what you're doing.
For example, you have to know how big your pointers actually are. They might not be the same size as plain int, especially if you're on a so-called 64-bit platform.
So if %x doesn't work, you might be able to get away with %lx, or %llx. But, most of the time, it's easier (and more portable) to just use %p.

Why does %u %d not work on UNIX/LINUX for printing addresses [duplicate]

This question already has answers here:
difference between printing a memory address using %u and %d in C?
(5 answers)
Closed 7 years ago.
I know that %d is for int, and %u for unsigned int and %p for the address.
But my question is we can print the address using %u,%d on a Windows machine but the same cannot be done on Linux.
For example:
#include<stdio.h>
int main() {
int x=15;
int *p;
p=&x;
printf("%d \n",x);
printf("%d \n",&x);
printf("%u \n",&x);
printf("%p \n",p);
printf("%x \n",p);
printf("%u \n",&p);
return 0;
}
OUTPUT:
15
2358812
2358812
000000000023FE1C
23fe1c
2358800
It is seen that the hex value(23fe1c) is changed to decimal using %d and %u.
But the exact same code gives error on Unix/Linux.
ERROR:
format (%d) expects arguments of type 'int', but argument 2 has type 'int*'
GCC has the ability to perform type checking on variadic functions, specifically using the format function attribute. This forces a check that the types passed as the variadic arguments exactly match the format string supplied.
GCC complains because the data types used in the printf format string and the passed parameters are not compatible. The portable and standard way to print a pointer is by using the %p specifier. However, you can find other places where people may use %x for the same purpose. As others have said, using %u and %d are not compatible with a pointer data type. They may work on some compilers like in the Windows case but other stricter compiler (like GCC in this case) could complain about the datatype being passed since int is not the same as int*. In order to use the %p notation you have to cast the pointer to void, as from the C99 standard:
p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
That's said, the %p is implementation defined so the output could change from an implementation to the other. Any way using %d or %u to print a pointer in general is not a good idea. Depending on the implementation a pointer could be a simple int or a long int. So you could get an undefined behavior if you try to print a pointer by using a %d or %u on a machine where the addresses are stored in long int variables.
If you would like to control the output then another option is to use uintptr_t provided by #include <inttypes.h>.

using %x to print the hex address contained in a pointer

i just read this short article http://karwin.blogspot.com/2012/11/c-pointers-explained-really.html which describes pointers really well. The author however says that the addresses are just these hex values, so he prints it with %x, but when i do this not only do i get a warning from the compiler saying i am passing a pointer instead of an unsigned int, but sometimes i get something that doesn't resemble an address at all (like 1C). Can somebody clarify the issue please?
%x expects its corresponding argument to have type unsigned int, which is why you get the warning and funky output. Use %p to display pointer values:
T *p = some_pointer_value;
...
printf( "p = %p\n", (void *) p );
%p expects its corresponding argument to have type void *. This is pretty much the only place you should explicitly cast a pointer to void * in C.
Edit
Just looked at the page. Be aware, that code sample is old (written ca. 1990) and uses K&R-style (pre-1989 standard) function definition syntax and implicit int all over the place. It's using %x to display pointer values because the %p conversion specifier wasn't added to the language until the 1989 standard.
It should not be used as a model of modern C programming practice.
His explanation of pointers is pretty decent, though.
%x is used to print a value in hex. While pointers are usually written in hex, there are other considerations for pointers that make %x a bad fit, like that 1C output you saw.
%p is meant for pointers, and is probably what you're looking for. It will format the pointer a bit better, since it knows that it's a pointer.
1C is a perfectly valid hex output, but it's odd for a pointer, since you expect certain special things to happen when displaying pointers, like having the correct length.
Since %x is meant for hex numbers, passing a pointer into it will give you a warning. One reason it gives you the warning is that pointers aren't necessarily the same size as an unsigned int.
%x expects an unsigned int, passing anything else is UB.
For printing a data-pointer, there is %p which can print void-pointers (type void*, the conversion is not optional), which will normally print it with hexadecimal notation.
If that's not satisfying you, consider casting the pointer to uintptr_t and printing that using the format-specifier-macros PRIxPTR or PRIXPTR from <inttypes.h>, for guaranteed hexadecimal output.
You even get to select the case used.
Pointers if manipulated with the intergral formats like %x or %u give undefined results. %p is recommended for pointers.
As far as the warning is concerned, %x expects an unsigned int, and your variable has probably different size or alignment requirement than unsigned int so you are getting the warning.
Values cannot be "hex". Values are just values. Meanwhile, "hex" is a way to represent values for human consumption. "Hex" is a notation.
Using %x directly on pointers is illegal though, since %x format specifier expects an unsigned int argument, not a pointer. A pointer can be cast to unsigned int type, and the result can be used with %x format specifier, but this will not work in general case since unsigned int type can easily be too narrow to properly represent the numerical address value.
In other words, forget about %x. It is hopelessly useless in that application. The author of your article is doing it very wrongly.
If you really want to print a pointer p through its conversion to integral type, the proper way to go would be this
printf("%" PRIxPTR "\n", (uintptr_t) p);
Note the use of uintptr_t type and PRIxPTR macro that stands for an implementation-defined format specifier associated with that type.
Other than that you can use a dedicated format specifier %p, which prints void * pointers and typically uses hex notation for that purpose.

Resources