C杂记(1)

来源:互联网 发布:猫吃老鼠会得病吗 知乎 编辑:程序博客网 时间:2024/05/16 15:40

    没事看了看《C和指针》,总结一些以前没注意到得或者疏忽掉的技术盲点。

    1.关于结构体的自引用,结构自引用不能引用这个结构本身,但是可以引用结构指针。原因是编译器在结构的长度确定之前就已经知道了指针的长度,所有这种引用时合法的,比如链表初始化的时候,都是用的这种方法添加指针域的。

Code:
  1. struct self_err2{   
  2.     int a;   
  3.     struct self_err2 *b;   
  4.     int c;   
  5. };  

    2.关于结构的存储分配,编译器是按照成员列表的顺序一个接一个的给每个成员分配内存的,只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。

Code:
  1. struct ALIGN{   
  2.     char a;   
  3.     int b;   
  4.     char c;   
  5. };  

    上面的代码为了满足边界对齐,成员a必须存储一个能够被4整除的地址,所有这个结构需要12个字节的内存空间。但是重新排列以后,让那些对边界要求最严格的成员首先出现,对边界要求最弱的成员最后出现。考虑以下结构

Code:
  1. struct ALIGN2{   
  2.     int b;   
  3.     char a;   
  4.     char c;   
  5. };  

    这个结构只占8个字节。

    3.作为函数参数的结构,这个地方只需要记住一点,如果函数对这个指针的间接访问次数超过2-3次,那么使用这个方法所节省的时间将远高于一条额外指令的时间。基本上,除非结构特别小的时候,给一个函数传递结构指针的效率远大于给函数传递一个结构。

    4.位段:这个以前几乎没有接触过(记得一次笔试遇到过,直接死掉)。位段必须声明为int,signed int或unsinged int类型。其次,成员名后面是一个冒号和一个整数。这个整数指定该位段所占用的位的数目。

Code:
  1. struct CHAR{   
  2.     unsigned ch    :7;   
  3.     unsigned font  :6;   
  4.     unsigned size  :19   
  5. };   
  6. struct CHAR   ch1;  

    使用位段的好处就是可以把奇数字节的数据包封装到一起,这样可以节省内存空间。

    5.关于malloc:这个函数和free都是维护一个可用的内存池,malloc从线程池取出一个连续的内存块,返回一个未初始化的指针。因此每个malloc返回的指针都要检查是不是NULL以确定是不是可用内存。malloc返回的指针是一个void*类型的。calloc和malloc区别是calloc分配一个初始化为0的指针。realloc用于修改一个原先已经分配的内存块的大小。所以使用realloc以后原先的指针作废,使用新的指针操作这个内存。

Code:
  1. /* 定义一个不易发生错误的分配器 */
  2. #include <stdlib.h>   
  3.   
  4. #define malloc   
  5. #define MALLOC(num,type)) (type *)alloc((num)*sizeof(type))   
  6. extern void *alloc(size_t size);  
Code:
  1. /* 不易发生内存分配器的错误的实现 */  
  2. #include <stdio.h>   
  3. #include "alloc.h"   
  4. #undef malloc   
  5.   
  6. void *alloc(size_t size)   
  7. {   
  8.     void *new_mem;   
  9.     new_mem = malloc ( size );   
  10.     if( new_mem == NULL){   
  11.         printf("out of memory!/n");   
  12.         exit(1);   
  13.     }   
  14.     return new_mem;   
  15. }  
Code:
  1. /* 一个使用很少引用错误的内存分配器的程序 */  
  2. #include "alloc.h"   
  3. void function()   
  4. {   
  5.     int *new_memory;   
  6.     /* 获得一串整形数的空间*/  
  7.     new_memory = MALLOC(25,int);   
  8.     /* ……………………*/  
  9. }  

 

    6.常见的动态内存分配的错误:对NULL进行解引用操作,内存进行操作的越界,释放并非动态分配内存,试图释放一块动态分配的内存的一部分以及一块动态内存被释放之后被继续使用。   

    7.内存泄露:这个问题倒是经常被提到,malloc后不释放,内存不断地被申请出来,导致内存最终被耗尽……

PS:以下这个分配的方法具有很好的可移植性。

Code:
  1. pi = malloc ( 25* sizeof(int))   
原创粉丝点击