理解C指针: 一个内存地址对应着一个值

转载 2015年07月07日 15:13:37
   一个内存地址存着一个对应的值,这是比较容易理解的。

    如果程序员必须清楚地知道某块内存存着什么内容和某个内容存在哪个内存地址里了,那他们的负担可想而知。
    汇编语法对“一个内存地址存着一个对应的数”,作了简单的“抽象”:把内存地址用变量名代替了,对内存地址的取值和赋值方式不变。
    c语言对此进行了进一步的抽象:变量 <==> (一个内存地址,对应的值)(这里忽略类型等信息)。

    把C语言中的基本类型(int,long,float等),指针,数组等还原为(一个内存地址,对应的值)后,就能更清淅地理解它们了。

    内存就相当于(addr,val)的大hash表,c语句的语义基本就是改变hash值。

    为了下文的方便,特定义如下语义(遵循C的标准语义):


    var  <==>  (addr, val)  (var为一个变量名,addr为var在内存中的首地址,val为var 的值)
    &var <==> addr
    var  <==> var作为左值出现(即等式左边)时,var等价于 addr;
               var作为右值出现(即等式左边)时,var等价于 val;
    *var <==> val


    注:符号"<==>" 右边出的等式 x = y(x是一个内存地址,y是一个值); 表示将内存地址为x的内容置为值y,如addr = 3表示置内存addr里的值为3


    现在利用上面的语义解释一下这些例子:
    int i = 3;
    假设 i的内存地址为 0x8049320 ,那么这句话的语义是0x8049320 = 3,经过i = 3后,i为(0x8049320,3)

    int b = i;
    假设 b的内存地址为 0x8049324 ,那么这句话的语义是0x8049324 = i对应的val = 3,此时b为(0x8049324,3)

    int *p = &b
    指针p也是一个变量,int **p,int *p[8],在这些申明中p都只是一个指针变量,它和其他的变量的不同之处在于它的大小是定的,它的类型信息只是编译器用来进行类型检查和其他一些作用的(如果没有类型检查,你可以用任何的方式对一个变量进行操作如int i; ****i = 3)。假设p的地址为0x8049328,则根据p = &b的语义p.addr = b.addr,p为(0x8049328,0x8049324)

    *p = 5;
    语义为 0x8049324 = 5,此时只改变了内存地址为0x8049324的值,即改变了b的值(0x8049324,5),而p的值并未改变

    int **q = &p; //如果写为int **q = &&i; gcc编译不通过
    假设q的内存地址为0x8049330,语义为 0x8049330 = addr(p) = 0x8049328;所以q为(0x8049330, 0x8049328)
    (int **q = &&i, 要是编译过了则q应该表示为(0x8049330, x),内存地址为x的地方表示为(x,0x8049320),那么地址x为多少呢? )

    **q = 6
    语义为 val(val(q)) = val(0x8049328) = 0x8049324 = 6,将内存地址为0x8049324的内容置为6,即将b的值置为6,b为(0x8049324,6)
    
    对于结构,这些语义也适用,因为结构里的成员也是有对应地址的,也能表示为(addr,val)的形式。    
   
    对“一个内存地址存着一个对应的值”的抽象程度越高,越不用关心底层,如java。 
    Haskell已经没有副作用之说了,更不用关心这些了。

    就这些。

c语言中通过指针将数值赋值到制定内存地址

1.一种直观的方法   假设现在需要往内存0x12ff7c地址上存入一个整型数0x100。我们怎么才能做到呢? 我们知道可以通过一个指针向其指向的内存地址写入数据,那么这里的内存地址...
  • leee7338
  • leee7338
  • 2015年06月24日 13:47
  • 1238

c++ 取地址运算 指针变量

一、取地址运算符&(内存地址) C++编译的程序占用的内存分为以下几个部分: 1.栈区:由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。与其它分区...
  • woailvmengmeng
  • woailvmengmeng
  • 2013年08月08日 10:56
  • 1199

指针指向数组并指定数组首地址的一种方法

今天想到C语言可以为一个参数指定地址,那么如何为一个数组指定首地址呢? 借鉴参数指定地址的方法,先想到用一个指针来指向一个数组,同时定义数组的数据类型,我是这样定义的 short (*ptr)[102...
  • doumeile1
  • doumeile1
  • 2016年05月16日 20:11
  • 2007

linux kernel虚拟内存地址耗尽一个实例分析

转自:http://www.cnblogs.com/xmphoenix/p/3627007.html引子现在android智能手机市场异常火热,硬件升级非常迅猛,arm cortex A9 + 1GB...
  • dahailantian1
  • dahailantian1
  • 2017年11月20日 17:49
  • 98

System.out.println当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步

 package com.yikuyi.volatileTest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; pub...
  • weixin_41237034
  • weixin_41237034
  • 2017年12月01日 11:32
  • 40

写了一个内存地址特征码搜索工具

实现了 1.搜索汇编上的地址 2.搜索匹配特征的内存地址 3.搜索到的地址再做+法计算,还没做读取内存指针,是直接16进制加法 4.支持通配符(就是用正则表达式来做的) 现在还不是很完善,因...
  • flashrhx2010
  • flashrhx2010
  • 2013年04月26日 16:59
  • 625

C语言中给指定的内存地址赋值(通过指针)

应用中的实际问题:通过I2C接口发送到MCU一个地址数据(unsigned char AdData),一个待写入数据(unsigned char DaData)。 希望将DaData的值写到MCU内存...
  • phenixyf
  • phenixyf
  • 2012年12月14日 15:38
  • 12581

u-boot移植随笔:一些内存地址的再次研究(二维数组及指针数组)

u-boot移植随笔:一些内存地址的再次研究(二维数组及指针数组)
  • subfate
  • subfate
  • 2011年03月22日 14:54
  • 884

借助U-boot进行一些内存地址的再次研究(二维数组及指针数组)

转自:http://www.latelee.org/porting-uboot/150-u-boot-porting-memory-again.html #include #includ...
  • gexueyuan
  • gexueyuan
  • 2012年04月19日 18:37
  • 593

为什么主引导记录的内存地址是0x7C00?

《计算机原理》课本说,启动时,主引导记录会存入内存地址0x7C00。 这个奇怪的地址,是怎么来的,课本就不解释了。我一直有疑问,为什么不存入内存的头部、尾部、或者其他位置,而偏偏存入这个比 32...
  • u012721052
  • u012721052
  • 2016年12月02日 11:22
  • 130
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:理解C指针: 一个内存地址对应着一个值
举报原因:
原因补充:

(最多只允许输入30个字)