针对struct name结构做的简要变幻

 问:在代码里遇到这样的结构:

struct name{

         intnamelen;

         charnamestr[1];

};

在后续的代码里使用内存分配技巧使数组成员用起来像有多个元素,namelen记录了数组元素的个数,感觉有些不合理,但是代码里确实存在,该如何解释?

 

答:不清楚这种做法的合法性,但是这种技术确实存在,但又不符合C语言的规定,下面看几个演化例子。

         例一:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct name{

         intnamelen;

         charnamestr[1];

};

 

struct name *makename(char *newname){

         char*name = newname;

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

         printf("sizeof(structname=%d,namelen_addr=%d, namestr_addr=%d)\n",(int)sizeof(structname),(int)&ret->namelen,(int)&ret->namestr);

         if(ret!=NULL){

                   ret->namelen=strlen(name);

                   strcpy(ret->namestr,newname);

         }else{

                   free(ret);

                   returnNULL;

         }

         returnret;

}

 

int main(int argc, char **argv){

         char*name = "test make name";

         structname *pn = makename(name);

         printf("len=%d,name=%s\n", pn->namelen, pn->namestr);

         return0;

}

此程序需要关注的地方是:

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

struct name结构的大小仅为sizeof(structname),这里却申请了sizeof(struct name)-1+strlen(newname)+1,这里大小就是name结构成员namelen的大小和newname所指字符常量的大小的总和。而name结构成员namestr悄悄的成为了刚刚申请的newname所指字符常量大小的首地址。

 

 

例二:将结构成员namestr数组扩容到100,代码实现如下:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define MAX 100

 

struct name{

         intnamelen;

         charnamestr[MAX];

};

 

struct name *makename(char *newname){

         char*name = newname;

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

         printf("sizeof(structname=%d,namelen_addr=%d, namestr_addr=%d)\n",(int)sizeof(structname),(int)&ret->namelen,(int)&ret->namestr);

         if(ret!=NULL){

                   ret->namelen=strlen(newname);

                   strcpy(ret->namestr,newname);

         }else{

                   free(ret);

                   returnNULL;

         }

         returnret;

}

 

int main(int argc, char **argv){

         char*name = "test make name";

         structname *pn = makename(name);

         printf("len=%d,name=%s\n", pn->namelen, pn->namestr);

         return0;

}

其实这个MAX扩容是多余的,和例一是一样的。

 

例三:

真正安全的做法是使用指针,而不是数组:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct name{

         intnamelen;

         char*namestr;

};

 

struct name *makename(char *newname){

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

         printf("sizeof(structname=%d,namelen_addr=%d, namestr_addr=%d)\n",(int)sizeof(structname),(int)&ret->namelen,(int)&ret->namestr);

         if(ret!=NULL){

                   ret->namelen=strlen(newname);

                   ret->namestr=malloc(strlen(newname)+1);

                   if(ret->namestr==NULL){

                            free(ret->namestr);

                            returnNULL;

                   }

                   strcpy(ret->namestr,newname);

         }else{

                   free(ret);

                   returnNULL;

         }

         returnret;

}

 

int main(int argc, char **argv){

         char*name = "test make name";

         structname *pn = makename(name);

         printf("len=%d,name=%s\n", pn->namelen, pn->namestr);

         return0;

}

 

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

将两次malloc调用合成一次的例子如例四。

 

例四:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct name{

         intnamelen;

         char*namestr;

};

 

struct name *makename(char *t_name){

         char*buf = malloc(sizeof(struct name)+strlen(t_name)+1);

         if(buf==NULL){

                   printf("bufmalloc error\n");

                   returnNULL;

         }

         structname *pname=(struct name *)buf;

         pname->namelen=strlen(t_name);

         strcpy(buf+sizeof(structname), t_name);

         pname->namestr=buf+sizeof(structname);

         returnpname;

        

}

 

int main(int argc, char **argv){

         char*test_name="test_name";

         structname *pn = makename(test_name);

         printf("namelen=%d,namestr=%s\n",pn->namelen, pn->namestr);

         return0;

}

 

结束

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值