① 闲聊c/c++: 谈内存(大/小端,高/低字节,高/低地址)
c/c++和其他语言最大区别在于: 指针
指针就是内存地址,一旦明白了指针与内存地址相关的内容,那理解其他语言,就易如反掌。
而且你可以把其他语言用的更加好,更加有效率
例如java/js/objc中为什么容器中只能存储引用类型?
如果存储基本数据类型(值类型),为什么会发生效率很低的装箱拆箱行为?
而c#为什么就不会呢?
你怎么才能让不使用的内存尽快被垃圾收集器回收过去?
还有很多涉及内存相关的内容,例如堆分配,栈分配等........
根据经验:
本篇目的:
是不是感觉很绕口啊,特难理解吧!
理解大小端的关键点是明白:
很容易理解 高低地址 了吧,就是书写顺序
高低字节是:左高右低
高低地址是:左低右高
根据大端的定义:
数据的高字节 保存在 内存的低地址 中,而 数据的低字节 保存在 内存的高地址 中
则内存存储的方式是:
DC是最高字节[ 最左 ],放在内存的最低地址[ 最左 ]
FF是最低字节[ 最右 ],放在内存的最高地址[ 最右 ]
按照这个规则,很容易知道,大端在内存存储的顺序是:
DC|6E|35|FF(和rgba = 0xDC6E35FF一致的顺序)
根据小端的定义:
数据的高字节 保存在 内存的高地址 中,而 数据的低字节 保存在 内存的低地址 中
则内存存储的方式是:
DC是最高字节[ 最左 ],放在内存的最高地址[ 最右 ]
FF是最低字节[ 最右 ],放在内存的最低地址[ 最左 ]
按照这个规则,很容易知道,小端在内存存储的顺序是:
FF|35|6E|DC(和rgba = 0xDC6E35FF相反的顺序)
先字节后地址:
附:今天老师带队一起写生去 文章我昨天半夜写的
② 内存中的存储单元的地址结构是几维
内存中的存储单元的地址结构是16位。
大部分16位和32位的CPU不允许将字或者长字存储到内存中的任意地址。比如Motorola68000不允许将16位的字存储到奇数地址中,将一个16位的字写到奇数地址将引发异常。
每一个单元的地址称为字节地址,任何相邻两个单元组成一个字地址,按编址原则约定用其中一个较小的地址来表示字地址。一个字由两个字节组成,则低字节对应低地址,高字节对应高地址。
相关应用:
在计算机中,由控制器解释,运算器执行的指令集是一个精心定义的数目十分有限的简单指令集合。一般可以分为四类:
1)、数据移动 (如:将一个数值从存储单元A拷贝到存储单元B)。
2)、数逻运算(如:计算存储单元A与存储单元B之和,结果返回存储单元C)。
3)、 条件验证(如:如果存储单元A内数值为100,则下一条指令地址为存储单元F)。
4)、指令序列改易(如:下一条指令地址为存储单元F)。
③ 计算机存储是低位在前高位在后吗应该怎么区分16进制中哪个是高位哪个是低
计算机存储:最小单位是字节,存储顺序(小端模式)为低位字节在前、高位在后
16进制:中最右边的是最低位,标记为第0位,向左边一位是第1位,这样一直到这个数据的第15位。
④ 一个占四字节的正整数,在内存中的存储方式是低8位在前(第一个字节),高8位在后(第四个字节)吗
字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。
你说的这张存储方式,是小端字节序。
⑤ C语言的内存地址是按什么顺序排列的:比如是按从大到小还是内存自动分配的,请举例
您问的具体是什么?
(1)是地址编号和集成电路里面(用显微镜看)各个单元的位置次序之间的关系?
(2)还是问程序中各个指令代码执行的次序和地址编号之间的关系?
(3)还是问程序中各个变量的次序和地址编号之间的关系?
如果是(1),那么
集成电路里面各个单元的位置次序,一般是不公开的。所以人们不知道它的次序是从左到右还是从右到左还是别的方式。据说,现在的布局大多是交叉分散排列的,因为程序中经常出现连续访问连续地址的操作,如此分散排列,可以使功耗分散,减小局部温升,延长器件寿命。
如果是(2),那么
一般的指令,除了跳转指令和调用、返回指令以外,普通指令都是按照地址连续增加的次序,连续排列的。而且,汇编语言中书写程序清单的次序,除了使用特殊伪指令规定地址(如ORG指令)处以外,都是按照地址编号连续增加的次序书写的。如此,除跳转、调用、返回指令外,书写的次序就是执行的次序。
如果是(3),那么
用汇编语言设计程序时,你可以随自己习惯,觉得怎么安排方便,就怎么安排。
如果是高级语言,那么,不同的编译程序,可以有所不同。
不过,如果是C语言,那么数组内部各个下标变量的地址,必须是按照下标由小到大地址也由小到大的次序连续安排。这是因为,C语言中,对指针的运算有严格规定。
例如p是指向整数的指针,则p+2就应该等于指向p所指的整数变量后面第二个整数变量的指针。于是(p+2)相应的物理地址,就应该等于p相应的物理地址加上2倍int变量的长度。 而对于数组,又是按照指针的概念来规定的。例如:a[2]就和*(a+2)完全等效。
⑥ 内存的低地址和高地址
地址都是32位的,如果用整形数(16位)保存的话,就要分高低位保存,可以用整形数组 int pointer[2]来实现,高16位存在pointer[1]中,低16位存在pointer[0]中,调用时直接把pointer强制转化成整形地址 (int *)pointer就好了。
ps不知道你为什么一定要这样做,地址本身就可以是一个变量,定义一个地址变量来保存不就好了么
⑦ 存储地址由的到的,由高到高
**静态存储区域分配。**内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
**在栈上创建。**在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释 放内存。动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大 小的堆空间将会产生堆内碎块。
📝 2、程序的内存空间
C语言在内存中一共分为如下几个区域,分别是:
内存栈区: 存放局部变量名;
内存堆区: 存放new或者malloc出来的对象;
常数区: 存放局部变量或者全局变量的值;
静态区: 用于存放全局变量或者静态变量;
代码区:存放函数体的二进制代码。
📝 3、区域的简单解释
栈区(stack)–由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆区(heap)–般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。
全局区(静态区)(static)–全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(RW), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(ZI)。程序结束后有系统释放
文字常量区–常量字符串就是放在这里的。 程序结束后由系统释放 (RO)
程序代码区–存放函数体的二进制代码。 (RO)
📝 4、动态内存与静态内存
静态分配内存:是在程序编译和链接时就确定好的内存。
动态分配内存:是在程序加载、调入、执行的时候分配/回收的内存。
📝 5、堆栈
堆和栈都是动态分配内存,两者空间大小都是可变的。
Stack: 栈,存放Automatic Variables,按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
通常是用于那些在编译期间就能确定存储大小的变量的存储区,用于在函数作用域内创建,在离开作用域后自动销毁的变量的存储区。通常是局部变量,函数参数等的存储区。他的存储空间是连续的,两个紧密挨着定义的局部变量,他们的存储空间也是紧挨着的。栈的大小是有限的。
Heap: 堆,自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。
通常是用于那些在编译期间不能确定存储大小的变量的存储区,它的存储空间是不连续的,一般由==malloc(或new)函数来分配内存块,并且需要用free(delete)==函数释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨着定义的指针变量,所指向的malloc出来的两块内存并不一定的是紧挨着的=,所以会产生内存碎片。另外需要注意的一点是,堆的大小几乎不受限制,理论上每个程序最大可达4GB。
每个线程都会有自己的栈,但是堆空间是共用的。