C指针和内存

时间:2012-03-09 16:43:53

标签: c pointers

我正在学习C,现在我撞墙了。我很难理解指针。

想象一下,我有这段代码:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define DELTA 33

int calls, seed=356;

int sum_ds(int a){    
 int d=DELTA;          
 calls++;               
 return a+d+seed; 
}                       

int main() {
    int num;                                
    int *ptr;
    int **handle;

     num = 14;                              
     ptr = (int *)malloc(2 * sizeof(int));  
     handle = &ptr;
     *(*handle+0) = num;                    
     *(*handle+1) = num+1;  
     *ptr = num-2;      
     ptr = &num;        
     *ptr = sum_ds(num-2);
}

让我们逐步了解。

1 - int调用创建一个名为calls的变量,并且不对其进行初始化,因此它包含垃圾。它存储在DATA上,假设存储器地址为0xFFAA。

2 - int seeds创建一个名为种子的变量,用整数356初始化。它存储在DATA上,让我们说内存地址为0xFFAB。

3 - int num创建一个名为num的变量,并且不对其进行初始化,因此它包含垃圾。它存储在STACK上,假设存储器地址为0xFFAC。

4 - int * ptr创建一个指向int的指针,并且不为其分配任何地址。它存储在STACK上,假设存储器地址为0xFFAD。

5 - int ** handle创建一个指向int指针的指针,并且不为其指定任何地址。它存储在STACK上,假设存储器地址为0xFFAE。 (很多人在这里写道)

6 - num = 14进入地址0xFFAC并在其上存储数字14。它是在STACK中完成的。

7 - ptr =(int *)malloc(2 * sizeof(int))在HEAP上,为2个整数分配内存大小,并存储第一个内存字节的地址(比如说0xFFZZ)(在STACK上) ptr所以现在* ptr指向那个内存地址。

8 - handle =&amp; ptr handle现在指向ptr。我相信它现在指向0xFFZZ上的任何东西(很多人在这里)

9 - *(* handle + 0)= num指向int指针的指针,现在指定的值为num(14)(许多人在这里许多人都不知道)

10 - *(* handle + 1)= num + 1指针的指针加上一个int,现在它的值被赋值为num + 1(15)(许多人在这里多了许多)

11 - * ptr = num-2 ptr的值点被赋值为num - 2(12)。我相信它会进入内存地址0xFFZZ并存储数字12。

12 - ptr =&amp; num ptr现在指向num,我相信它现在指向0xFFAC。

13 - * ptr = sum_ds(num-2)ptr指向的值是sum_ds的返回值。我相信0xFFAC它被分配了401(12 + 33 + 356)

这是对的吗?

3 个答案:

答案 0 :(得分:4)

  

1 - int调用创建一个名为calls的变量,并且不对其进行初始化,因此它包含垃圾。它存储在DATA上,假设存储器地址为0xFFAA。

     

2 - int seeds创建一个名为种子的变量,用整数356初始化。它存储在DATA上,让我们说内存地址为0xFFAB。

一个小细节:sizeof(int)大于1(在大多数主流平台上都是4,所以第二个地址不能比第一个高1。除此之外,AFAIK到目前为止你是正确的。< / p>

  

3 - int num创建一个名为num的变量,并且不对其进行初始化,因此它包含垃圾。它存储在STACK上,假设存储器地址为0xFFAC。

     

4 - int * ptr创建一个指向int的指针,并且不为其分配任何地址。它存储在STACK上,假设存储器地址为0xFFAD。

另一个小细节:在大多数主流平台上,堆栈向下增长,因此第4个地址将小于第3个。除此之外,AFAIK到目前为止你是正确的。 (此外,数据段,堆和堆栈上的地址在现实生活中会有很大不同。)

  

7 - ptr =(int *)malloc(2 * sizeof(int))在HEAP上,为2个整数分配内存大小,并存储第一个内存字节的地址(比如说0xFFZZ)(在STACK上) ptr所以现在* ptr指向那个内存地址。

要挑剔,'Z'不是十六进制数:-)所以我们说它是0x1000而不是。

  

8 - handle =&amp; ptr handle现在指向ptr。我相信它现在指向0xFFZZ上的任何东西(很多人在这里)

不,handle现在包含ptr的地址,即0xFFAD间接地 - 通过ptr - 确实指向0x1000(在您的示例中为0xFFZZ)。

  

9 - *(* handle + 0)= num指向int指针的指针,现在指定的值为num(14)(许多人在这里许多人都不知道)

基本上是正确的。您使用的符号并不是最容易处理的,这使您更难以了解正在发生的事情。在第8步之后,*handle相当于ptr。由于指针和数组在许多常见情况下可以互换,*(ptr + 0)等同于ptr[0],也等同于*ptr

  

10 - *(* handle + 1)= num + 1指针的指针加上一个int,现在它的值被赋值为num + 1(15)(许多人在这里多了许多)

与前一点类似,您实际上正在分配ptr[1] = num+1。请注意,虽然ptrint*,但ptrptr + 1之间的地址差异等于sizeof(int),如上所述,通常为4 *ptr

  

11 - * ptr = num-2 ptr的值点被赋值为num - 2(12)。我相信它会进入内存地址0xFFZZ并存储数字12。

是的,这会覆盖步骤9中设置的值。

  

12 - ptr =&amp; num ptr现在指向num,我相信它现在指向0xFFAC。

正确。

  

13 - * ptr = sum_ds(num-2)ptr指向的值是sum_ds的返回值。我相信0xFFAC它被分配了401(12 + 33 + 356)

正确。由于上一步使num等同于num = sum_ds(num-2),因此此调用也等同于{{1}}。

答案 1 :(得分:1)

由于calls在任何函数之外,因此它是static变量。静态变量初始化为0。

由于num是局部变量(auto存储类),因此初始化。

在您的第9点,*(*handle+0) = num;可能最容易解释为handle = &ptr,因此*handle = ptr,因此这基本等同于*(ptr+0) = num;,这是ptr[0] = num; (反过来)相当于+1

对于第10点,你会得到几乎相同的东西,除了两个案例中的ptr[1] = num+1;,所以它是*ptr=num-2;

对于第11点,*(ptr+0)会覆盖第9点所写的内容 - 即* ptr与ptr[0] = num-2;相同,因此这相当于ptr

在第12点,您的num已设置为num=sum_ds(num-2);,这是正确的。这意味着在第13点,分配相当于{{1}}

答案 2 :(得分:1)

变量有一个地址,并且在该地址存储的是您刚刚放置的值:

int a = 10;

右?

指针是一种存储另一个变量地址的变量。 所以......

int a = 10;
int *p = &a;

这意味着“p”存储了具有您想要使用的值的“a”的地址。

执行以下代码,您将了解:     printf(“%p%p%d%d \ n”,p,&amp; a,* p,a);