C语言中变量在内存中的保存与访问

CPU通过内存地址访问元素

int i=0x12345678

假如i的地址是0x100,那么在小端存储体系中

地址数值
0x1000x78
0x1010x56
0x1020x34
0x1030x12

CPU访问内存需要同时具备两个因素:

  • 内存基址:从哪里访问内存——就是地址
  • 内存布局:访问几个字节(怎样解析,解释方法)

定义变量时指明的数据类型就是指明内存布局,i是int型变量,所以CPU知道连同0x100后面四个地址一起组成i的值

强制类型转换改变的就是解析方法,也就是内存布局

char p= *(char*)i

这样CPU会只将地址0x100中的0x78解析为一个char类型的字符然后赋给p

同理 short p=*(short*)i

得到的short型变量p的值是0x5678

这样看来,只要给定了内存基址和内存布局就可以不用实际变量名得到变量值

比如 *(short *)0x102实际上就是值0x1234

对于结构体变量来说也是如此解析的(虽然其中有内存对齐问题)

struct foo{
	int first;
    short second;
    char third;
}*pfoo;

对于语句 pfoo->first中的->操作符,它首先算出右侧的变量在左侧结构体中的偏移量,然后让左侧变量的地址(指针所指地址)加上偏移量就实际上得到了右侧变量的内存基址,然后根据右侧变量类型,也就是得到了它的内存布局,这样两个因素都具备了也就得到了它的值

在一些实际应用中,会看到这样的链表应用方法:将链表嵌入到数据结构中(学校里用的链表大概都是将数据结构嵌入链表)

struct data_in_list{   //数据嵌入双向链表
    int price;
    ....   //一些可能要用的数据
    struct data_in_list *next;
    struct data_in_list *pre;
}

//下面是链表嵌入数据结构中
struct list{
    struct list *next;
    struct list *pre;
}

struct list_in_data{
    ...//一些会用到的数据
    struct list lnode;
}

比如在2.6版本的Linux内核中,这种数据结构是很常见的,进程描述符task_struct结构体中就包含链表节点,所有进程描述符是用一个双向链表连起来的,而根据链表节点访问结构体就是用到了上面说的CPU访问数据的两个要素

type 是结构体类型

address 是结构体中链表节点

field 是链表节点类型

(type*)(address - &(((type*)0)->field))  //(type*)0表示内存基址是0的type型变量,&符获得了field在type中的偏移量
//这样可以根据链表节点得到其所在的type结构体的地址,实际上可以根据结构体中任一变量得到整个结构体
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值