指针及相关内存的理解

前言

你是否在C代码里面看到一些方法签名 method( A ** pointer ) method( A * pointer ) 脑袋就会充血,总是感觉会绕一下。什么是 指针 ?什么是 指针的指针 ?
看谭浩强的时候,总感觉是什么都懂,但是一看到真实的代码,就感觉理解上还不够深入。

最近在看 Linux 的原理,顺便捡起 C语言 编码。结合 linux 的内存结构,反而对指针有了进一步的了解,希望这篇文章对你有帮助。

PS: 🦉 linux 的C语言的开发环境配置,后续补充一篇文章

程序例子说明

所有代码都是运行在 64位 Centos7.4中


int a = 123;    
printf("a address: %lx\t value:%d \n", &a, a); 
//a address: 7fffffffdf5b  value:123 
printf("\n");

int * b = (int *)malloc(sizeof(int) * 1); *b = 11;
printf("b address: %lx\t value:%lx pointed-value:%d \n", &b, b, *b);  
//b address: 7fffffffdf58  value:602010 pointed-value:11 
printf("\n");

int * c = &a;
printf("c address: %lx\t value:%lx pointed-value:%d \n", &c, c, *c);  
//c address: 7fffffffdf50  value:7fffffffdf5b pointed-value:123

代码下面就是输出的信息,我们一个个看。

int a = 123;

int a = 123; 
printf("a address: %lx\t value:%d \n", &a, a);  
//a address: 7fffffffdf5b  value:123

简单理解

  • 就是在 stack 中有创建一个 变量a,数据类型是 int,赋值是 123

深入理解

  • stack 地址 7fffffffdf5b 上,分配了 4Bytes 内存,创建变量 a,是 int 类型,value 是 123。
  • 变量 a 包含:1. 内存地址,stack 7fffffffdf5b ; 2. 值, 123,占用内存 4 Bytes

后续的内存图,都是根据打印出来的变量值,来绘画出真实内存值的情况。

根据值和图得知,变量a 代表一个地址,地址指向 stack 一段内存,内存值是 123。

int * b = (int *)malloc(sizeof(int) * 1); *b = 11;

int * b = (int *)malloc(sizeof(int) * 1); *b = 11;
printf("b address: %lx\t value:%lx pointed-value:%d \n", &b, b, *b);  
//b address: 7fffffffdf58  value:602010 pointed-value:11

简单理解

  • 创建变量 b,是 int pointer,指向 heap 内存地址;在 heap 对应的地址申请内存,数据类型是 int,赋值是 11

深入理解

  • heap 地址 60 20 10 上,分配了 4Bytes 内存,是 int 类型
  • stack 地址 7f ff ff ff df 58 上,创建变量 b,分配了 8Bytes 内存,是 int piointer 类型,value 是 60 20 10
  • heap 地址 60 20 10 上赋值,value 是 11
  • 变量 b 包含:1. 内存地址,stack 7f ff ff ff df 58 ; 2. 值, 60 20 10 ,占用内存 8 Bytes


int * b = (int *)malloc(sizeof(int) * 1);
根据值和图得知,变量b 代表一个地址,地址指向 stack 一段内存,内存值是 60 20 10
:::info
变量是 stack地址对应的内存
:::

int * c = &a

int * c = &a;
printf("c address: %lx\t value:%lx pointed-value:%d \n", &c, c, *c);  
// c address: 7fffffffdf50  value:7fffffffdf5b pointed-value:123

正常理解

  • 创建变量c,是 int pointer,指向变量 a 地址

深入理解

  • stack 地址 7f ff ff ff df 50 上,创建变量 c,分配了 8Bytes 内存,是 int piointer 类型,value 是 7f ff ff ff df 5b (就是 变量a 的地址)
  • 变量 c 包含:1. 内存地址,stack 7f ff ff ff df 50 ; 2. 值, 7f ff ff ff df 5b ,占用内存 8 Bytes


:::info
指针变量,对应内存的值,可以是 heap 地址,同样可以是 stack 地址
:::

总结

  1. 变量,就是 一个Stack地址地址指向的内存 而已;不论是 普通变量,指针变量,和 指针的指针变量
  2. 创建变量
    1. 变量的地址,一定是 Stack地址
    2. 分配内存,可以分配在 stack 中,也可以分配在 heap 中,看情况而定

再进一步思考

指针仅仅是一种数据类型

pointer 就是和 int char 等基础的类型一样,变量都是定义在内存中,并且占用了一定容量内存保存数据。


int a = 123;  
int * b = (int *)malloc(sizeof(int) * 1); 

printf("size of pointer: %d\n", sizeof(a));  //4
printf("size of pointer: %d\n", sizeof(b));  //8 (64bits机器)

总结

指针就是数据类型,不要给他吓到;定义变量的时候, int * = int-pointer ,可能会理解更加容易。
变量,就是定义某种数据类型;所以 变量 的通用规则,也同样应用到指针上。

创建变量

printf("a address: %lx\t value:%d \n", &a, a);  
//a address: 7fffffffdf5b  value:123 
printf("b address: %lx\t value:%lx pointed-value:%d \n", &b, b, *b);  
//b address: 7fffffffdf58  value:602010 pointed-value:11

&a &b 都是指向了 stack 中的地址,地址中的内存 保存着 value

  • int a = 123,定义在 7f ff ff ff df 5b 地址上,分配了4Bytes内存,保存的是 int类型,value 是 123。
  • int * b = (int *)malloc(sizeof(int) * 1); ,定义在 7f ff ff ff df 58 地址上,分配了8Bytes内存,保存的是 int pointer类型,value 是 602010。

602010 是指向 heap 中的地址,同时地址后续的 4Bytes 内存,保存的是 11。

总结

  1. 创建变量 = stack内存区 指定一段地址 + 分配指向内存
    1. 基础变量,直接在内存中赋值
    2. 指针,里面保存的是内存地址
  2. 创建变量,转换成机器语言,就是 address , memory spaceset value into memory space,机器是 **不管 **你什么 a,b,c

使用变量在入参中

void output(int a , int * b ) {
	printf("value:%d \n", a);  //value:123 
	printf("value:%lx \n", b);  //value:602010
}

上图中,在 output栈帧中,开辟内存,复制 **a****b** 的内存值。方法体内的 a b 地址,就是 output栈帧中的地址。

总结

  1. 变量入参,在子栈帧内存中新开地址,使用 原变量内存value来赋值到新开地址对应的内存中
  2. value 在 父栈帧 和 子栈帧 都有一份的,值是一样的;且你改 子栈帧,是不会影响到 父栈帧的值
  3. 如果去修改 *value,那么有机会改动到 同值value指向内存

指针类型

_printf("b address: %lx\t value:%d pointed-value:%d \n", &b, b, *b);_

  1. &b 就是变量b 的地址,就是 stack 地址,我们非常少使用到这个值,因为 stack 会弹出 frame 的,所以保存都是临时保存
  2. b 就是 变量b地址 指向的内存值,variable value,这个在 入参 中也有体现
  3. *b 就是 变量b's value 作为地址 指向的内存值

总结:

  1. 指针类型,与普通变量一样,内存里面的值是一段内存地址

总结

  1. 指针类型变量,不需要畏惧,就是一种数据类型变量,同样是分配地址和内存
  2. 在理解栈帧、堆、栈 上去理解指针会更加通彻
  3. C语言,就是操纵内存的语言
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江南西肥肥

你的小小鼓励是给我巨大的奖励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值