简体   繁体   English

地址如何分配给指针变量? 他们遵循任何模式吗?

[英]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? 为什么为p1和p2分配的地址以1为增量,而对于p3和p4分配的地址以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. 在您的系统上(我猜是x86_64),指针的大小为8个字节。 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. 例如,在32位x86系统上,指针为4字节,并且还有许多其他平台具有特殊的指针大小。

Also the size of a char is defined to be 1, so the first pointer sits one byte after ch . 而且char的大小定义为1,因此第一个指针位于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 : 还有它是如何工作的X86-64(你的电脑可能有)一个很好的例子在这里

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. 与您的问题相关的是xx yy zz部分。 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 . xx的地址最高,然后依次是yyzz To illustrate this, you could do (&xx)[-1] and might get the value of yy . 为了说明这一点,你可以做(&xx)[-1]可能得到的值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. ch分配在地址298923415。指针p1分配在下一个字节298923416。从那里开始,每个指针分配8字节的倍数,建议使用64位系统。

This simply means that the compiler allocates char differently than pointers. 这仅表示编译器分配char方式与分配指针的方式不同。 This is because char is 1 byte and has no alignment requirements, so it may be placed at a misaligned address. 这是因为char是1个字节,并且没有对齐要求,因此可能会将其放置在未对齐的地址处。

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): 输出(x64 Windows PC,十六进制地址):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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