I have a text file with the memory addresses of certain components of a program. For instance part of that text file looks like this:
00400000-0040b000
or
7f9ae612f000-7f9ae62ee000
I have already read the file into my program and assigned a char[] with the first address (00400000).
I also have a structure with a null pointer
struct myStruct
{
void *address;
}
And I would like the pointer *address to have the value of 0x00400000, how would I do this?
Thank you for your help.
Use sscanf() to parse the string as a hex integer and then typecast the resulting integer to a void* pointer. For example:
char str[] = "00400000";
unsigned long ul;
struct myStruct s;
sscanf(str, "%lx", &ul);
s.address = (void*) (uintptr_t) ul;
If the same instance of the program printed "00400000-0040b000" then reading a void* back via scanf("%p"... is possible. Else the result is undefined.
p specifier:
Matches an implementation-defined set of sequences, which should be the same as the set of sequences that may be produced by the %p conversion of the fprintf function. The corresponding argument shall be a pointer to a pointer to void. The input item is converted to a pointer value in an implementation-defined manner. If the input item is a value converted earlier during the same program execution, the pointer that results shall compare equal to that value; otherwise the behavior of the %p conversion is undefined. C11dr §7.21.6.2 12
struct myStruct x;
if (fscanf(stream, "%p", &x.address) == 1) Success();
Source:
First of all %x writes unsigned int. There is no guarantee that pointer size = unsigned int size.
As there is no format specifier which takes uintptr_t, you need to manualy check your pointer size in program and then select correct format specifier.
Therefore, to comply with the standard, you have to manually use the sizeof operator on void * and unsigned int and compare them. If they are equal, you can use %x as the format.
Otherwise, you need to take appropriate action, and use a different format.
Of course, if this is just a test project, it won't matter to do a dynamic check at runtime. Just hardcode it to the correct value. Be sure to leave a FIXME though, so you can come back and add dynamic checking later.
Additionally,
We discussed in the comments about the format specifiers, and you specified that %lx had correct results. Since it is guarenteed that %lx can print a value of at least uint32_t, your void * must be at least the size of uint32_t.
Additionally number 2,
Source.
If you aren't happy with the implementation-defined behaviour of %p, then use C99 <inttypes.h> and uintptr_t instead:
printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);
Please note that the above solution requires C99 to work properly.
Related
Do memory addresses expressed in hexadecimal always need to start with '0x'? Or can it be any other? What are the conditions?
#include <stdio.h>
int main(void)
{
int n = 50;
int *p = &n;
printf("%p\n", p);
}
Here the output I got is '000000000062FE14'. Shouldn't it start with 0x?
The format of %p's outlook is implementation-defined. On gcc and clang (at least the versions used by tio.run), it appears to get a 0x prefix (and use lowercase for hex digits a-f), on your compiler it does not (and uses A-F instead). Both behaviors are legal.
If you want your code to behave in a consistent way, you'll need to use %x or %X as the base format code, so you can precisely specify the inclusion of 0x exactly once. To preserve the width behavior you've already got (always a fixed number of zero-padded hex digits sufficient to represent any pointer value for that architecture), you'll need to explicitly specify the width as well. The final version (that ensures you get 0x000000000062FE14 on any 64 bit pointer architecture) is:
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
int n = 50;
int *p = &n;
printf("0x%0*"PRIXPTR"\n", 2*(int)sizeof(p), (uintptr_t)p);
}
Breaking that down:
#include <inttypes.h> provides (through stdint.h) the typedef for uintptr_t, and the macros for printing it portably
0x is prefixed on manually (because the # modifier won't add 0x for an input of zero, and we want it there even for NULL pointers)
0* says "pad with zeroes out to a width of the first argument"
PRIXPTR is a macro that produces the appropriate format code for uppercase hex relative to a uintptr_t (use PRIxPTR for lowercase hex)
2*(int)sizeof(p) is passed to match the use of * for the width, which allows us to compute the size needed for exactly as many digits as the architecture requires to print any pointer of that type in the same fixed width. The cast to int is needed because * explicitly expects int for that argument, and sizeof produce size_ts; I'm fairly sure I can rely on sizeof for a pointer returning a value that fits in int though, so the cast is safe. :-)
(uintptr_t)p casts to an integer type sufficient to hold any pointer to void (which means it can hold any pointer to object type, but outside of POSIX, there's no guarantee it can hold a function pointer); the x/X codes work with integers, not pointers, so it can't be passed as a pointer without violating the spec.
Technically, support for [u]intptr_t is optional (and requires at least C99/C++11, but hopefully that's not an issue). But I strongly suspect the systems that don't provide [u]intptr_t have pointers larger than any provided integer type (they'd be weirdo systems where uintmax_t may be smaller than the number of bits in a pointer, e.g. a system where programs are natively aware of memory across the cluster and can directly address it with 128 bit global address pointers that can refer to non-local memory, but the processor is still 64 bits, and the compiler doesn't bother to support combining two 64 bit registers to represent a single 128 bit integer, so uintmax_t is too small to fit a pointer address), so you'd have no way of handling them portably anyway (you'd be stuck with %p).
Tthe %x format has an option %#x which means that "0x" gets appended to the output. This isn't specified for %p however, but there are ways to safely convert the pointer to a large integer and then print:
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
int n = 50;
int *p = &n;
printf("%"PRIxPTR "\n", (uintptr_t)p);
printf("%#"PRIxPTR "\n", (uintptr_t)p);
}
Outputs something along the lines of:
7ffce1c44c04
0x7ffce1c44c04
Since the format output by %p is "implementation-defined" by the C standard (§7.21.6.1 The fprintf function) and POSIX (fprintf()), different implementations do it differently. Some include a 0x prefix; some don't (and some might use 0X, but I don't remember seeing that in use). Many use lower-case letters for the digits 10-15; it seems your implementation uses upper-case, which is unusual. Some implementations pad with leading zeros; many do not. On macOS, a null pointer prints as 0x0 while other pointers print values like 0x7ffeebcf53bc, so the width isn't necessarily fixed.
There is no requirement that there is uniformity across implementations. If you want uniformity, use the type uintptr_t and macros such as PRIXPTR (or PRIxPTR) from <inttypes.h>.
#include <assert.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
static_assert(sizeof(void *) == sizeof(void (*)(void)),
"Object pointers are not the same size as function pointers");
#ifndef PTR_WIDTH
#define PTR_WIDTH "12"
#endif
#define PTR_FORMAT "0x%." PTR_WIDTH PRIXPTR
int main(void)
{
printf("Object pointers:\n");
int i = 0;
int *a = malloc(3 * sizeof(*a));
int *p = (int *)4100;
printf("%p\n", (void *)0);
printf("%p\n", &i);
printf("%p\n", a);
printf("%p\n", p);
printf(PTR_FORMAT "\n", (uintptr_t)0);
printf(PTR_FORMAT "\n", (uintptr_t)&i);
printf(PTR_FORMAT "\n", (uintptr_t)a);
printf(PTR_FORMAT "\n", (uintptr_t)p);
printf("Function pointers:\n");
printf("%p\n", (void *)(uintptr_t)main);
printf("%p\n", (void *)(uintptr_t)printf);
printf(PTR_FORMAT "\n", (uintptr_t)main);
printf(PTR_FORMAT "\n", (uintptr_t)printf);
free(a);
return 0;
}
On a Mac, this produces:
Object pointers:
0x0
0x7ffee094539c
0x7ffed9405a10
0x1004
0x000000000000
0x7FFEE094539C
0x7FFED9405A10
0x000000001004
Function pointers:
0x10f2bddd0
0x7fff205f30a8
0x00010F2BDDD0
0x7FFF205F30A8
You will probably see different values, but the output should be similar. On a Mac, I've never seen an address with more than 12 hexadecimal digits, so I set PTR_WIDTH to 12 (as a string). You can set it to 16 (e.g. gcc -o pp29 -DPTR_WIDTH='"16"' pp29.c) if you want the maximum width for a 64-bit system, or use 8 if you're on a 32-bit system.
Note that you cannot officially convert function pointers to object pointers or vice versa directly in C:
§6.2.5 Types ¶28:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.
48) The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
§6.3.2.3 Pointers ¶6-8:
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.
7 A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
8 A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
68)
In general, the concept ''correctly aligned'' is transitive: if a pointer to type A is correctly aligned for a pointer to type B, which in turn is correctly aligned for a pointer to type C, then a pointer to type A is correctly aligned for a pointer to type C.
However §6.2.3.2 ¶6 provides an escape hatch — convert to an appropriate integer type — but be aware that in theory (though rarely in practice) there could be platforms where there isn't an integer type that can hold function pointers. That is why there are two consecutive casts when printing the function addresses directly.
See also §7.20.1.4 Integer types capable of holding object pointers:
1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
It would be a very unusual machine where the uintptr_t or intptr_t types are not available.
Do memory addresses of hexadecimals always need to end in '0x' form?
Answer: No, they don't.
From C11:
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.
It's implementation-defined. And the pointer must be cast to void *, else your code invokes undefined behaviour.
printf ("%p\n", (void *) p);
%p is a format specifier for "pointers" and the interpretation, unlike some others, is "implementation dependent" so one cant really have an expectation of consistency, which is fair, given different environments can have different addressing semantics
In the following code, we pass pointer to a string and it works fine but it doesn't works for pointer to an integer. I want to know why ?
#include <stdio.h>
int main(){
char *astring = "afdv";
printf("%s",astring);
int a;
a = 1000;
int *ptr = &a;
printf("\n%d", ptr);
}
In the first printf you did NOT send a pointer. You de-referenced the pointer and hence, you are actually sending a character. Likewise if you want to print an integer, send *ptr, the dereferenced value of the integer pointer.
I'm guessing the source of your confusion to be this-
printf("%s", string_ptr);
perfectly prints the string value instead of the pointer value but
printf("%d", integer_ptr);
prints the pointer value instead of the integer value.
This is because the way printf is implemented. When it sees a %s in the format string, it considers the corresponding parameter as a pointer to a NULL-terminated string. And goes looking for the value of that string at the address contained in the pointer.
But when it sees a %d, it considers the corresponding parameter as an integer value and prints it out directly.
The change in behavior is because types like integer, floats etc are smaller and finite in size and can be passed to printf as values directly. But a string can be arbitrarily large in size. So it makes sense to pass it as a pointer and let printf go find the actual value using the pointer.
Because the language specification says so.
The %s conversion specifier expects its corresponding argument to have type char *; printf will then print out the sequence of characters starting at that address until it sees the string terminator.
The %d conversion specifier expects its corresponding argument to have type int; printf will then print out the text representation of that value as a signed decimal integer.
Check your handy C reference manual for the complete list of conversion specifiers and the types of arguments they expect. If you don't have a handy C reference manual, my preferred one has been C: A Reference Manual since the late 1980s, although the current edition only covers up to C99.
If you use %d and pass something that isn't an integer, then the behavior is undefined. The compiler isn't required to yell at you for passing an argument of the wrong type. If you run the code, anything may happen. In practice, you'll usually get garbled output. If you pass something that isn't a pointer for %s, you may get a runtime error.
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);
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.
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.