c之统一分配内存技巧

来源:互联网 发布:部落冲突数据大全2017 编辑:程序博客网 时间:2024/04/28 08:14

1.struct name {

int namelen;

char namestr[1];

};

我们声明这样的结构,然后用一些内存技巧是namestr数组用起来好像有多个元素,namelen记录了元素个数。

#include <stdlib.h>

#include <string.h>

struct name *makename (char *newname)

{

struct name *ret = malloc(sizeof(struct name)-1 + strlen(newname)+1);

if(ret != NULL) {

ret->namelen = strlen(newname);

strcpy(ret->namestr, newname);

}

return ret;

}

这个函数分配了一个name结构的实例并调整它的大小,以便将请求的名称(不是结构声明所示的仅仅一个字符)置入namestr域中。

但这种技术不能保证在所有的实现上是可移植的,仔细检查数组边界的编译器可能会发出警告。

2.改写为:

#include <stdlib.h>

#include <string.h>

#define MAX 100

struct name {

int namelen;

char namestr[MAX];

};

struct name *makename (char *newname)

{

struct name *ret = malloc(sizeof(struct name) - MAX + strlen(newname)+1);

if(ret != NULL) {

ret->namelen = strlen(newname);

strcpy(ret->namestr, newname);

}

return ret;

}

此处MAX应该比任何可能存储的名字长度都大,但是这种技术似乎也不完全符合标准的严格解释。

真正安全的正确做法是使用字符指针,而不是数组。

3.

#include <stdlib.h>

#include <string.h>

struct name {

int namelen;

char *namep;

};

struct name *makename (char *newname)

{

struct name *ret = malloc(sizeof(struct name));

if(ret != NULL) {

ret->namelen = strlen(newname);

ret->namep = malloc(ret->namelen + 1);

if(ret->namep == NULL) {

free(ret);

return NULL;

}

strcpy(ret->namep, newname);

}

return ret;

}

把长度和字符串保存在同一块内存中的“方便”已经不复存在了,而且在释放结构的实例的时候需要两次调用free。

4.改进:

为了保持连续性,可以直截了当地将两次malloc调用合成一次,这样也可以只用一次调用free就能释放。

struct name*makename (char* newname)

{

char *buf = malloc(sizeof(struct name) + strlen(newname) + 1);   //一次分配出struct name 8字节和 namep 4字节的空间,这样分配的空间是连续的

struct name *ret = (struct name *)buf;                       // 只是将分配出的8字节格式转换为struct name *

ret->namelen = strlen(newname);               //   将参数传过来的newname 长度算出给 namelen

ret->namep = buf + sizeof(struct name); // namep是一个指针,此指针指向buf[8] ,即分配的namep 的空间

strcpy(ret->namep, newname);  // 将newname拷贝到namep指针指向的空间处

return ret;

}

像这样一次malloc调用将第二个区域接上的技巧只有在第二个区域是char型数组的时候才可移植。
0 0
原创粉丝点击