首页 文章

C指针和内存

提问于
浏览
2

我正在学习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种子创建一个名为种子的变量,用整数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)存储在ptr上(在STACK上),所以现在 ptr指向该内存地址 .

8 - handle =&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 =&num ptr现在指向num,我相信它现在指向0xFFAC .

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

这是正确的吗?

3 回答

  • 1

    1 - int调用创建一个名为calls的变量,并且不对其进行初始化,因此它包含垃圾 . 它存储在DATA上,假设存储器地址为0xFFAA . 2 - int种子创建一个名为种子的变量,用整数356初始化 . 它存储在DATA上,让我们说内存地址为0xFFAB .

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

    3 - int num创建一个名为num的变量,并且不对其进行初始化,因此它包含垃圾 . 它存储在STACK上,假设存储器地址为0xFFAC . 4 - int * ptr创建一个指向int的指针,并且不为其分配任何地址 . 它存储在STACK上,假设存储器地址为0xFFAD .

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

    7 - ptr =(int )malloc(2 * sizeof(int))在HEAP上,为2个整数分配了内存大小,第一个内存字节的地址(假设为0xFFZZ)存储在ptr上(在STACK上)现在 ptr指向该内存地址 .

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

    8 - handle =&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 .

    11 - * ptr = num-2值ptr指定值为num - 2(12) . 我相信它会进入内存地址0xFFZZ并存储数字12 .

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

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

    正确 .

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

    正确 . 由于上一步使 *ptr 等效于 num ,因此此调用也相当于 num = sum_ds(num-2) .

  • 1

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

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

    在你的第9点, *(*handle+0) = num; 可能是最容易破译的,因为要记住 handle = &ptr ,因此 *handle = ptr ,所以这基本上相当于 *(ptr+0) = num; ,这反过来相当于 ptr[0] = num; .

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

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

    在第12点你是正确的, ptr 已被设置为指向 num . 这意味着在第13点,分配相当于 num=sum_ds(num-2);

  • 4

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

    int a = 10;
    

    对?

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

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

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

    执行下面的代码,你就会明白:printf(“%p%p%d%d \ n”,p,&a,* p,a);

相关问题