理解C指针: 一个内存地址对应着一个值
来源:互联网 发布:淘宝访问深度怎么计算 编辑:程序博客网 时间:2024/05/16 18:14
一个内存地址存着一个对应的值,这是比较容易理解的。
如果程序员必须清楚地知道某块内存存着什么内容和某个内容存在哪个内存地址里了,那他们的负担可想而知。
汇编语法对“一个内存地址存着一个对应的数”,作了简单的“抽象”:把内存地址用变量名代替了,对内存地址的取值和赋值方式不变。
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语言对此进行了进一步的抽象:变量 <==> (一个内存地址,对应的值)(这里忽略类型等信息)。
把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已经没有副作用之说了,更不用关心这些了。
就这些。
0 0
- 理解C指针: 一个内存地址对应着一个值
- 理解C指针: 一个内存地址对应着一个值
- 一个简单例子理解C语言指针
- 将特定的内存地址赋给一个指针
- 指针和内存分配一个最基本理解
- 关于C指针的一个问题(获取内存)
- C指针一个简单的小错误(1)-内存分配
- 关于c/c++struct,指针,数组,内存地址的点滴理解
- C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例
- 对指针的一个理解
- 编写一个使用指针的c函数,交换数组a和数组b中的对应元素
- 一个数组就是一个地址,一个指针就是一个地址的地址
- 一个指向二维数组元素的指针变量,内存地址怎么不连续?
- 一个指针与地址的例子
- 一个例子让你理解c++的指针(传递动态内存)
- 深入理解c指针-内存管理
- 如何确定一个虚拟地址对应的汇编代码
- IIS之Web服务器 一个IP地址对应多…
- dede织梦上传图片出现提示302错误ERROR解决方法
- mongodb常用操作命令整理
- Android GPS学习笔记—GpsLP初始化
- "黑马程序员"Java面向对象(2)
- AppStore App加速审核
- 理解C指针: 一个内存地址对应着一个值
- 有关Unity3D的OnRenderImage()和Blit()的一些问题
- 死亡笔记1---java语言的四大特性以及方法重载 方法重写的区别以及new创建对象所用到的知识点
- 组织机构管理
- 项目管理小知识——Alpha版本,Beta版本
- 软件架构的数据流总结(一)
- 【C语言】调整数组使奇数全部都位于偶数前面
- Struts框架之Action中多个业务方法处理
- Objective-C - NSObject常用方法