作者:将登太行的2602939913 | 来源:互联网 | 2023-09-10 10:33
一、CC类型大小问题类型32位环境下所占字节数64位环境下所占字节数char11shortint22int44longint48longlongint88float44doubl
一、C/C++类型大小问题 类型 32位环境下所占字节数 64位环境下所占字节数 char 1 1 short int 2 2 int 4 4 long int 4 8 long long int 8 8 float 4 4 double 8 8 char* 4 4 int * 4 4
特别地,NULL占用4字节。
二、数据存储问题 (一)、C/C++内存中五大区域 其在内存中分配的位置图如下。
1、堆(Heap) 存放着由操作malloc/free,new/delete分配/释放的内存(不太安全的内存管理方式)。堆可以动态地扩展和收缩,这个区域通常较大,并向高地址扩展。动态内存的生存期人为决定,使用灵活。缺点是容易造成内存泄漏 (Memory Leakage),频繁操作会产生大量内存碎片。
(1)、内存碎片(Memory Fragment) 内存碎片分为两种:外部碎片和内部碎片。
①、外部碎片(External Memory Fragment) 外部碎片指的是还没有被分配 出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。 外部碎片是出于任何已分配区域或页面外部的空闲存储块。这些存储块的总和可以满足当前申请的长度要求,但是由于它们的地址不连续或其他原因 ,使得系统无法满足当前申请。 多道可变连续分配只有外部碎片。
②、内部碎片(Internal Memory Fragment) 内部碎片就是已经被分配 出去(能明确指出属于哪个进程)却不能被利用的内存空间; 内部碎片是处于区域内部或页面内部的存储块。占有这些区域或页面的进程并不使用这个存储块。而在进程占有这块存储块时,系统无法利用它 。直到进程释放它,或进程结束时,系统才有可能利用这个存储块。 单道连续分配只有内部碎片。多道固定连续分配既有内部碎片,又有外部碎片。
③、内存碎片减少的方法(Solutions) 采用控制页边界对齐 和内存字节对齐 、将相邻空闲内存块连接起来、内存池 等先进的内存管理机制。
2、栈(Stack) 存放函数的参数值 ,局部变量 ,函数执行结束时会被自动释放。栈内存分配运算内置于处理器的指令集中,效率高,但是容量有限。(栈方便用来保存/恢复调用现场,可以把其看成一个暂时保存和交换数据的区域)
3、BSS段(Block Started by Symbol Segment) 用来存放程序未初始化 的全局变量。不保存在硬盘上,只是记录数据所需空间的大小,程序开始执行之前,由内核进行初始化为0。BSS段属于静态内存分配,即程序一开始就将其清零了。
4、数据段(Data Segment) 用来存放程序已初始化 的全局变量。数据段属于静态内存分配。其中static静态变量存放在数据段中,而非栈区。
5、代码段(Code Segment/Text Segment) 用来存放程序执行代码 。这部分区域的大小在程序运行前就已经确定,通常为只读(某些架构也允许代码段为可写,即允许修改程序),也有可能包含一些只读的常量,例如字符串常量等。
三、结构体和数组的问题 如下所示,假如系统的数据存储方式为小端模式(Little Endian),三个输出应该是什么?
#include struct data { uint16_t a; uint8_t b; uint16_t c; } * example; int main ( int argc, char * argv[ ] ) { uint8_t num[ ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 } ; example = ( struct data* ) num; printf ( "%x %x %x" , example- > a, example- > b, example- > c) ; system ( "pause" ) ; return 0 ; }
输出结构是 0x0201 0x03 0x0605,这是为什么呢?看下面的数据存放图。
可以得出结构体中16位的a等于0x0201,8位的b等于0x03,16位的c等于0x0605。由于内存对齐,成员b只用到了低字节0x03,0x04就被舍弃了(实际上还存在内存里,但用不到,除非在b的地址加上一字节偏移,如使用*(&(example->b)+1)
就能读到0x04)。
参考链接: C/C++内存分配方式与存储区