简体   繁体   中英

How are the addresses given to pointer variables? Do they follow any pattern?

#include<stdlib.h>

int main()
{
   char ch, *p1, **p2, ***p3, ****p4;
   ch='a';
   p1=&ch;
   printf("%c %d %c\n", ch, p1, *p1);

   p2=&p1;
   printf("%d %d %c\n", p2, *p2, **p2);

   p3=&p2;
   printf("%d %d %d %c\n", p3, *p3, **p3, ***p3);

   p4=&p3;
   printf("%d %d %d %d %c\n", p4, *p4, **p4, ***p4, ****p4);
}

The output looks like :

a 298923415 a                                                                                                                 
298923416 298923415 a                                                                                                          
298923424 298923416 298923415 a                                                                                                
298923432 298923424 298923416 298923415 a           

Why is it that for p1 and p2 the address assigned is in increment of 1 and for p3 and p4 the address assigned is in increment of 8?

Do the addressing follow any pattern as they are assigned in continuous memory location?

Your objects are laid out sequentially in memory in this case. They don't necessarily have to be though. The compiler can lay things out in memory however it wants.

In your case, your memory looks something like this:

298923415 +-----------+
          |    'a'    | ch
298923416 +-----------+
          |           |
          |           |
          |           |
          | 298923415 | p1
          |           |
          |           |
          |           |
          |           |
298923124 +-----------+
          |           |
          |           |
          |           |
          | 298923416 | p2
          |           |
          |           |
          |           |
          |           |
298923132 +-----------+
          |           |
          |           |
          |           |
          | 298923424 | p3
          |           |
          |           |
          |           |
          |           |
298923140 +-----------+
          |           |
          |           |
          |           |
          | 298923432 | p4
          |           |
          |           |
          |           |
          |           |
          +-----------+

Remember that, on most modern systems, pointer-to-object types are just integers whose job is to store a memory address. On your system (I'm guessing x86_64) pointers have a size of 8 bytes. This is totally system-dependent though. For example, a pointer is 4 bytes on 32-bit x86 systems, and there are plenty of other platforms with exotic pointer sizes.

Also the size of a char is defined to be 1, so the first pointer sits one byte after ch .

What happens depends on what the compiler does. There's no guarantee in the language itself, but usually they get placed close to each other on the stack. There's a nice example of how it works on x86-64 (what your PC probably has) here :

The example uses the following code:

long myfunc(long a, long b, long c, long d,
        long e, long f, long g, long h)
{
    long xx = a * b * c * d * e * f * g * h;
    long yy = a + b + c + d + e + f + g + h;
    long zz = utilfunc(xx, yy, xx % yy);
    return zz + 20;
}

x86-64上的堆栈框架布局

Relevant to your question is the xx yy zz part. Like in your question, those are variables declared on the stack. As you can see on the image, they got placed next to each other. xx has the highest address, then comes yy and then zz . To illustrate this, you could do (&xx)[-1] and might get the value of yy . Note that this is undefined behavior and only works because we know what the compiler does with it, in any different setup it might not work, could cause bugs and crash the program (or worse).

Also, consider this post about memory alignment, which may cause gaps between your data in order to make it run faster.

You are reading your output the wrong way. ch is allocated at address 298923415. The pointer p1 is allocated at the next byte, 298923416. From there on, each pointer is allocated by a multiple of 8 bytes, suggesting a 64 bit system.

This simply means that the compiler allocates char differently than pointers. This is because char is 1 byte and has no alignment requirements, so it may be placed at a misaligned address.

Generally, the compiler is free to allocate variables where it likes and you have no guarantees. And there is no point in discussing stack memory layout without a specific system in mind.

Fixing your example into something clearer, the results are unspectacular:

#include <stdio.h>

int main (void)
{
   char ch = 'a';
   char*    p1 = &ch;
   char**   p2 = &p1; 
   char***  p3 = &p2;
   char**** p4 = &p3;
   printf("ch:\t%p\n", (void*)p1);
   printf("p1:\t%p\n", (void*)p2);
   printf("p2:\t%p\n", (void*)p3);
   printf("p3:\t%p\n", (void*)p4);
   printf("p4:\t%p\n", (void*)&p4);
}

Output (x64 Windows PC, hex addresses):

ch:     000000000022FE4F
p1:     000000000022FE40
p2:     000000000022FE38
p3:     000000000022FE30
p4:     000000000022FE28

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM