C要点(一)

 
.sizeof()
1.sizeof 的使用 :sizeof 操作符以字节形式给出了其操作数的存储大小 .
sizeof 操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、 void 类型等。
 2. sizeof 的结果 :sizeof 操作符的结果类型是 size_t ,它在头文件中 typedef unsigned   int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。
int unsigned   int  、 short   int unsigned   short  、 long   int  、 unsigned   long  、 float double long   double 类型的 sizeof  在 ANSI   C 中没有具体规定,大小依赖于实现,一般可能分别为 2 2 2 2 4 4 4 8 10
当操作数是指针时, sizeof 依赖于编译器。 near 类指针字节数为 2 far huge 类指针字节数为 4 。一般 Unix 的指针字节数为 4
当操作数具有数组类型时,其结果是数组的总字节数 , 联合类型操作数的 sizeof 是其最大字节成员的字节数。
结构类型操作数的 sizeof 是这种类型对象的总字节数,包括任何垫补在内 .
 
如果操作数是函数中的数组形参或函数类型的形参, sizeof 给出其指针的大小。
struct MyStruct
{
char dda;// 偏移量为 0 ,满足对齐方式, dda 占用 1 个字节;
double dda1;// 下一个可用的地址的偏移量为 1 ,不是 sizeof(double)=8
// 的倍数,需要补足 7 个字节才能使偏移量变为 8 (满足对齐
// 方式),因此 VC 自动填充 7 个字节, dda1 存放在偏移量为 8
// 的地址上,它占用 8 个字节。
int type // 下一个可用的地址的偏移量为 16 ,是 sizeof(int)=4 的倍
// 数,满足 int 的对齐方式,所以不需要 VC 自动填充, type
// 放在偏移量为 16 的地址上,它占用 4 个字节。
} // 所有成员变量都分配了空间,空间总的大小为 1+7+8+4=20 ,不是结构
// 的节边界数(即结构中占用最大空间的类型所占用的字节数 sizeof
//(double)=8 )的倍数,所以需要填充 4 个字节,以满足结构的大小为
//sizeof(double)=8 的倍数
所以该结构总的大小为: sizeof(MyStruc) 1+7+8+4+4=24 。其中总的有 7+4=11 个字节是 VC 自动填充的,没有放任何有意义的东西 .
  .malloc() alloc()
 
C语言跟内存分配方式
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多
C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等.
其中alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且没有
初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间.
calloc则将初始化这部分的内存,设置为0. 而realloc则对malloc申请的内存进行大小的
调整 . 申请的内存最终需要通过函数 free 来释放 . sbrk 则是增加数据段的大小 ;
 malloc/calloc/free基本上都是C函数库实现的,跟OS无关.C函数库内部通过一定的
结构来保存当前有多少可用内存.如果程序malloc的大小超出了库里所留存的空间,那么
将首先调用brk系统调用来增加可用空间,然后再分配空间.free时,释放的内存并不立即
返回给os,而是保留在内部结构中. 可以打个比方: brk类似于批发,一次性的向OS申请大
的内存,而malloc等函数则类似于零售,满足程序运行时的要求.这套机制类似于缓冲.
使用这套机制的原因: 系统调用不能支持任意大小的内存分配(有的系统调用只支持固定大小以及其倍数的内存申请,这样的话,对于小内存的分配会造成浪费; 系统调用申请内存代价昂贵,涉及到用户态和核心态的转换.
函数malloc()和calloc()都可以用来分配动态内存空间,但两者稍有区别。    
    malloc()函数有一个参数,即要分配的内存空间的大小:     
    Void *malloc(size_t size);   
    calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小:    
    void *calloc(size_t numElements,size_t sizeOfElement);
    如果调用成功,函数malloc()和calloc()都将返回所分配的内存空间的首地址。
    malloc() 函数和calloc()函数的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题。
    calloc() 函数会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初始化为零;如果你是为指针类型的元素分配内存,那么这些元素通常(但无法保证)会被初始化为空指针;如果你是为实数类型的元素分配内存,那么这些元素可能(只在某些计算机中)会被初始化为浮点型的零。
    malloc() 函数和calloc()函数的另一点区别是calloc()函数会返回一个由某种对象组成的数组,但malloc()函数只返回一个对象。为了明确是为一个数组分配内存空间,有些程序员会选用calloc()函数。但是,除了是否初始化所分配的内存空间这一点之外,绝大多数程序员认 为以下两种函数调用方式没有区别:
    calloc(numElements ,sizeOfElement);
    malloc(numElements *sizeOfElement) ;
    需要解释的一点是,理论上(按照ANSIC标准)指针的算术运算只能在一个指定的数组中进行,但是在实践中,即使C编译程序或翻译器遵循这种规定,许多C程序还是冲破了这种限制。因此,尽管malloc()函数并不能返回一个数组,它所分配的内存空间仍然能供一个数组使用(对realloc()函数来说同样如此,尽管它也不能返回一个数组)。
    总之,当你在calloc()函数和malloc()函数之间作选择时,你只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。
    当程序运行过程中malloc了,但是没有free的话,会造成内存泄漏.一部分的内存没有
被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内
存,是的系统可用内存不断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回
收所有的资源.因此,适当的重起一下程序,有时候还是有点作用.
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值