1:强制类型转换的问题
2:空间配置器的原理以及作用。
3:复习
C语言是支持隐式类型的转换的,但是这个转换的过程比较的“简陋”只用一个赋值运算符就完事了,但是有些类型转换是比较危险的,比如静态变量强制转换位非静态变量,因为静态变量存在寄存器中,编译器取的时候是寄存器中取得,如果用指针转换成普通类类型了,系统就会去内存中取这个变量,然而寄存器中的这个变量并没有变,就会出错。
比如定义一个const int i=19;然后将他的指针强转成普通的int此时然后解引用指针改变i的值,打印这时会发现变量i没有改变。如下图:
变量i还是10没变,这是因为编译器从寄存器取东西的结果,此时只需要用volatile修饰这个静态变量就可以让编译器去内存中读取i变量了。如下:
上面的类型转换是相对而言比较危险的,其他的数据类型向下转换也有一定的精度丢失。
所以c++中规范了这样的转换过程:
static_cast:隐式类型转换专用:格式static_cast<void>(void elem);
reinterpret_cast:强制类型转换,格式同上。
const_cast:去除const修饰。格式同上。dynamic_cast:这是向上兼容,用于类的转换,一般用于派生类转换为基类;多态中的基类引用或者指向派生类的指针。也是这个原理。
dynamic是通过虚表来判断这个是否可以强转的,所以必须有虚函数才能使用。
空间适配器:
一个程序在运行时肯定会有很多地方需要申请堆内存,然而内核是很忙的,它需要管理很多个程序进程的空间申请和释放问题,如果程序每次都为一点点内存就去跑去问内核要内存,这大大影响了效率,而且这些内存切片了后再还回去就是碎片内存了,这些内存又很小,而且地址又不连续基本就属于不能用的内存碎片,于是就设计了内存池,这个程序一次把内存申请够,用的时候直接切,就不会有这么多事了。但是切到的这些小内存又很难管理于是就用哈希捅管理这些内存。
一般内存池分为一级和二级,一级很简单就是一个malloc函数申请一块空间,这是程序需要的较大的内存,去直接申请的内存,而二级内存池,就是用的一次申请好的内存,使用的时候切下来好几个挂在哈希桶上,用的时候用,不用的时候又挂回去。这样的设计不仅解决了内存申请的效率问题,又解决了碎片化内存过多的问题。
数组指针的定义方式:int*(*parr)[10];这是一个存入类型为整形指针的名字为parr的数组的指针。、
函数指针的定义方式与数组指针的方式很像,int(*fun)(int int);这是一个返回值类型为整形的名字为fun的函数指针,他有两个整形参数。
strlen和sizeof,strlen求字符串的长度他不将/0算入其中,而sizeof计算字符串本身的大小。
memmove和memcpy memcpy可以复制内存数据,但是如果两个串要复制的地方重合了,这个就坏了。必须要用memmove来解决这个问题。因为memmove对于重复的情况用倒着复制的方法。
大端和小端:大端是数据低位存于高地址而小段是低位存于低地址,假设地址从左到右由高到低,那么32位下小端一个整形1就是00000001,大端为01000000,那么将这个整形指针强转为char类型,这时在解引用这个char*,此时编译器以处理char类型的方式来处理int类型的指针,就是说读取一个字节解引用,如果是小端就会得到1,因为最小的位存在低地址中,否则就是大端。
结构体大小的计算:
1:结构体的大小必须是最大元素大小的整数倍,数组按照每个单元大小计算。
2:结构体中的元素只能放在本身元素的整数倍的地方。
3:如果嵌套了结构体,则这个嵌套的结构体放在自己最大元素大小的整数倍上。
malloc开辟空间不初始化,calloc开辟空间并初始化为零,realloc重新对一个已有的内存开辟更大的空间,如果足够延长则延长原空间,如果不够,则去开一个新的拷贝数据,并释放旧空间。
预处理:
标签:类型转换,复习,int,C语言,问题,cast,内存,变量,指针 From: https://www.cnblogs.com/qjwxlj/p/17419241.html