1

I thought the ptr's address and a's address is the same with each other. And also I thought the ptr's address is the same with its int value converted from pointer.

But the result of console denied me.What's the reason? How can i understand the result.

#include <stdio.h>

int main() {
    int a[5] = {1, 2, 3, 4, 5};
    int *ptr = (int *) ((int) a);

    printf("a's address: %p \n", a);
    printf("ptr's address: %p \n", ptr);
    printf("ptr's int value: %x", (int)ptr);

    return 0;
}

the console's result is

a's address: 0x7ffee8d30600 
ptr's address: 0xffffffffe8d30600 
ptr's int value: e8d30600

ps

I have edited the title, and the original ambiguous title is "What is the difference between pointer's address and pointer's int value"

sunhang
  • 367
  • 2
  • 11
  • 2
    You get three things as a pointer. Like any variable in C, It *has* an address (ex: the expression `&ptr`). A pointer also *holds* an address (ex: the expression `ptr`). And finally, you can get what it points to (ex: the expression `*ptr`). Each of these has a specfic type, `int **`, `int*`, and `int`, respectively. That said, what/who ever told you "the ptr's address is the same with its int value" was being naive. And `int *ptr = (int *) ((int) a);` is utter nonsense. – WhozCraig Jun 02 '19 at 03:12
  • 1
    Especially on x86-64 platforms, where a pointer is 64 bits in size and casting it to an int would remove information. – Psi Jun 02 '19 at 03:17
  • You're not printing the pointer's address, you're printing the pointer's value. – William Pursell Jun 02 '19 at 03:21
  • @WhozCraig Thank your answer. I have edited the title and some content, which may lead to ambiguity – sunhang Jun 02 '19 at 03:40
  • A pointer is simply a normal variable that holds the *address of* something else as its value. In other words, a pointer *points to* the address where something else can be found. For example, while `int a = 5;` stores the immediate value `5` as its value, `int *b;` creates a pointer to `int`, and `b = &a;` stores the address of `a` (the memory address where `5` is currectly stored) as its value. If you need the value stored at the memory address held by a pointer, you *dereference* the pointer using the unary `'*'` operator, e.g. `int c = *b;` will initialize `c = 5`). – David C. Rankin Jun 02 '19 at 03:43

3 Answers3

1

Not really what you are trying to achieve here. An int only contains a 32-bit value. Thus, (int)ptr will only return a 32-bit value of ptr's address, which is the lower 4 bytes you get.

hongwu
  • 11
  • 1
1

C has a type uintptr_t which lets you store a pointer value:

void *p = …;
uintptr_t u = (uintptr_t)p;
void *q = (void *)q;
// here q is equivalent to p

On many platforms, u stores the address of the object that p point to, just like p does, and u and p have the same representation in memory. This is not an obligation: C implementations are allowed to use a different representation. But using the same representation is the most obvious way to meet the requirement in the C standard.

Note that a conversion from uintptr_t to a pointer type only gives a usable pointer if the uintptr_t value was obtained from a pointer that is still valid. This can be subtle. Even on processor architectures where the representation is the same (which is almost all of them), compilers are allowed to assume that you don't do too crazy things and to optimize accordingly. See responses to the Cerberus survey for some examples.

In your case, you didn't try to store the pointer value in an uintptr_t, you tried to store it in an int. This failed because on your platform, int is too small to store a pointer value. Evidently, on your platform, pointers are 64-bit values and int are 32-bit values. This is a very common arrangement.

  • a is the address of the array. (It's a pointer to the first element of the array, and on your platform a pointer is just represented by an address.). In this particular run, it's 0x7ffee8d30600. Nothing remarkable there.
  • (int) a converts the address of a to an int value. This is implementation-defined. Your implementation does the usual thing: since int is too small, it truncates the value. Truncating the address above to an unsigned 32-bit value yields 0xe8d30600. To get a signed value, the most significant bit becomes the sign bit, so a happens to be negative: a is -388823552.
  • p is (int *) ((int) a). This conversion is again implementation-defined, and your implementation again does the same thing as most. It takes the 32-bit signed int value -388823552, extends it to the desired width and shifts it to the unsigned range, yielding 264 - 388823552 = 0xffffffffe8d30600.
  • (int)p applies the same truncation process as (int)a above, and again yields -388823552. But you're using the %x specifier to print it out, so this value is converted to unsigned (a 32-bit type on your platform), which gives the value 232 - 388823552 = 0xe8d30600.
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
0

I have understand it. The machine is based with 64bit address. Converting the address to int value will loss the upper value of address. So here the a's address is different from ptr's address.

If to use pointer in C++, we can use intptr_t or preferably uintptr_t

sunhang
  • 367
  • 2
  • 11