0

I am trying to create a pointer to an address in memory given by the user, but I am having problems. I actually manage to create the pointer and print its address, but I never succeed to print or change its content. Would any one kindly explain why?

Here is the code I'm trying to run:

    int m = 10;
    printf("&m = %d (address in dec.)\n", &m);

    printf("Enter an address: ");
    int address;
    scanf("%d", &address);
    int* p = (int*) address;

    printf("p = %d (address in dec.)\n", p);
    printf("*p = %d (value)\n", *p);

and here is a console of me interacting with the program:

&m = 1220033252 (address in dec.)
Enter an address: 1220033252
p = 1220033252 (address in dec.)
Segmentation fault

Same thing happens if I try an address different from &m.

Thanks!

A F
  • 25
  • 5
  • 1
    How do you know the address is valid for that process? If it is, is it readable? The addresses seen by a running program often don't correspond directly to the physical addresses... physical "pages" are mapped into the program's address space by the system when/where appropriate, and may be restricted to certain types of access. Multiple running copies of the same program may even have the same (virtual) memory addresses for their variables, but have those (virtual) addresses mapped to totally different parts of physical memory so they can't access each other's data. – Dmitri Dec 28 '19 at 02:55
  • try `%p` rather than `%d` in the first statement (your code causes undefined behaviour by using the wrong format specifier in printf) – M.M Dec 28 '19 at 04:16

2 Answers2

5

int is not necessarily big enough to hold a pointer. It's usually 32 bits, but pointers are 64 or 128 bits on many systems now.

You can use the built-in typedef intptr_t to declare an integer big enough to hold a pointer to integer.

int m = 10;
printf("&m = %" PRIiPTR " (address in dec.)\n", (intptr_t)&m);

printf("Enter an address: ");
intptr_t address;
scanf("%" SCNiPTR, &address);
int* p = (int*) address;

printf("p = %" PRIiPTR " (address in dec.)\n", (intptr_t)p);
printf("*p = %d (value)\n", *p);

For more information, see Why / when to use `intptr_t` for type-casting in C? and string format for intptr_t and uintptr_t

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    @chux-ReinstateMonica You're right, I didn't read the other question carefully. – Barmar Dec 28 '19 at 03:37
  • Thanks, you are right. I was being deceived by printing the addresses using %d for decimal. I was also using %X to print in hexadecimal, which was not giving me the full address neither. Using intptr_t thoroughly solved the problem. – A F Dec 28 '19 at 14:57
2

Shortly, you're hitting the fact that int and int * aren't the same types.

First, %d should be used for values of type int, which as not the same as pointer type. Most likely, on your machine size of pointer is bigger than size of int, so you are printing not the pointer, but just a part of it. For example, in my case the pointer value is 140734913221608 (0x7fff668293e8), but 1719833576 (0x668293e8) gets printed. Because of that, you enter a pointer to a random unallocated memory, and when you dereference it, segmentation fault occurs.

Second, the code for reading pointer value has the same problem. Additionally to wrong format string for scanf, you are trying to store the value in a variable of type int. A variable of pointer type should be used instead.

As for getting the code working, check out Correct format specifier to print pointer or address? for an in-depth explanation.

mizabrik
  • 133
  • 6
  • Thanks, you are right. I was being deceived by printing the addresses using %d for decimal. I was also using %X to print in hexadecimal, which was not giving me the full address neither. Using intptr_t thoroughly solved the problem. – A F Dec 28 '19 at 14:58