原创

基于 汇编、C、Java 浅析 指针引用 和 内存分配

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014303844/article/details/81627820

关于编程语言中的内存分配,以及指针(引用)是比较重要的,这里对曾学过的知识结合工作经验做一些梳理。

从计算机底层基础语言到上层高级语言分析:
1.汇编
简要介绍一下汇编程序的 规则定义,编写和执行

DATA SEGMENT ;数据段开始 (变量定义)
word DW ? ;双字 (注意高低位)
str  DB 'Hello world!' ;单字 串(数组)
DATA ENDS  ;数据段结束

CODE SEGMENT ;代码段开始
ASSUME    CS:CODE,DS:DATA ;,ES:EXTRA,SS:STACK 指定数据段 代码段
START:  ;主程序起始地址定义
   MOV      AX,DATA  ;寄存器 初始化 数据段
   MOV      DS,AX
   MOV      AX,EXTRA
   Mov      AX,1020H ;立即寻址 直接让AX里面放入数字1020H (ax = 1020)
   Mov      AX,[1020H] ;直接寻址 让AX里面存放 内存地址1020H 中存的值 指针?引用? (ax = *(1020))
   ... 数据处理 赋值 计算 编码 
   MOV,AH,4CH
   INT 21H ;通过中断来调用设备接口 输入输出(IO)之类
CODE ENDS ;代码段结束
END START ;结束汇编

这里是些寄存器(固定存储单元,定死的变量空间?)定义了解一下:
  AH(8位)  AL(8位)  AX(16位)   (AX和AL又称累加器)
  BH(8位)  BL(8位)  BX(16位)   (BX又称基址寄存器,唯一作为存储器指针使用寄存器)  
  CH(8位)  CL(8位)  CX(16位)   (计数器,CX用于字符串操作,控制循环的次数,CL用于移位)
  DH(8位)  DL(8位)  DX(16位)   (数据,DX一般用来做32位的乘除法时存放被除数或者保留余数)

这里主要了解代码段里面的变量寻址的七种方式中的两种
假设一个内存块,分为了两部分,一部分负责加载代码,一部分负责存储值,代码一段一段的加载和执行,代码中用到的变量可能是立即数(基本数据类型? 值本身就是所代表的值),也可能是一个地址(引用?指针?可以通过该地址去找到对应的其他值)

2.C

#include<stdio.h> 
int ox = 6;//全局变量
int main(int argc, char **argv){
//赋值或者说复制符号‘=’是比较特殊的啊,=号左边必须是一个’容器‘,右边必须是一个值,
    int ax = 1; //把值1复制到ax里,           
    int bx = ax; //把ax地址里的值复制到bx里,
    int *cx = &bx;//变量cx(指针类型) (&取地址) 把bx的地址里的值复制到cx里,
    char *st = "hello world";//变量str(指针类型) 定义常量区字符串 并且把常量串的地址复制到st里
    chat *ht = (chat*)malloc(sizeof(char)*4);//分配的堆区块 并且把该块的地址复制到ht里
    chat *ct = ht;//把ht本身的值复制到ct里,注意这里ht的值是存储的地址,也就是说赋值的是地址
    int dx = *cx;//(*取地址里存的值) 把cx本身的值作为地址 去取到的值复制到dx里,所以dx=1
    strcpy(ht, "heap");//赋值 
/** 内存模型
* 栈(局部变量)         静态区(常量/全局)  堆(malloc)
*                     cx[1000]  6
* ax[0000]     1      [1020]    'h'    [2000]    'h'      
* bx[0020]     1      [1030]    'e'    [2010]    'e'
* cx[0040]     0002   .'llo worl'..    [2020]    'a'
* st[0060]     1020   [10e0]    'd'    [2030]    'p'
* ht[0080]     2000   [10f0]    '\0'   [2040]    '\0'
* ct[00a0]     2000   
* dx[00c0]     1
*/
    printf(*str);
    return 0;
}

有个概念,叫做索引(index),我们通过一个key(地址)去获取到实际的值,一个映射表,数学里的函数,y = f(x),通过x可以获取y,x的存储区域可能并不和y所存储的区域相同,可能是在同一个内存里,可能一个在内存一个在硬盘里,甚至在不同的计算机上,只是寻址有不同的实现方式

3.Java

public class Hello {
        int ox = 0;
        Hello(){
            //Java中 基本数据类型 都有对应的封装对象类型
            int ax = 1; //把值1复制到ax里,           
            int bx = ax; //把ax的值复制到bx里,
            int[] ar = {2,3,4};//堆上创建数组块对象 并复制地址到ar里
            //Java 会确保一个字符串常量只有一个拷贝!!!
            String s1 = "str1";//栈分配引用,静态区分配字符串
            String s2 = "str1";//栈分配引用,由于存在该静态串,出于优化指向相同串
            String s3 = new String("str1");//栈分配引用,堆分配字符串 
            Map<String, Object> map = new HashMap<>();//创建一个int-map型变量,把新堆对象的地址复制到变量里
            Map map2 = map;//把map的值(引用地址)复制到map2里
            map.put("key0", "value0");//调用map地址指向的对象的方法
            map2.put("key", "value");//调用map2地址指向的对象的方法 由于map map2的存储的值是相同的,所以操作的都是同一个对象
    }
    public static void main(String argc[]) {
        new Hello();
    }
}
/** 内存模型
* 栈(局部变量)         静态区(常量/全局)           堆(new)
*                     ox[1000]    0             [2000] {2,3,4}
* ax[0000]    1       [1020]    'str1'          [2060] 'str1'
* bx[0020]    1                                 [20a0] HashMap{}
* ar[0040]    2020
* s1[0060]    1020
* s2[0080]    1020
* s3[00a0]    2060
* map[00c0]   20a0
* map2[00e0]  20a0
*/

Java中对于字符串是比较特殊的处理,保证常量池中唯一,字符串不可变(immutable),做了优化处理,
至于引用,个人看来和指针没有什么差别,可以认为是不可变指针

文章最后发布于: 2018-08-13 14:40:06
展开阅读全文
0 个人打赏

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 1024 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览