C/C++结构体内尾部0字节字符数组技巧
2009-01-14 08:58
281 查看
最近工作,学习到一个有意义的C/C++结构体或类的操作技巧,看看如下结构体的定义
//设置字节对齐为1,来反应结构体的真实大小
#pragma pack(push,1)
struct _pack_1
{
//cLen指明cmd指向的缓冲区大小
int cLen;
//在vc中不可以为0,那么设置为1;
char cmd[0];
};
struct _pack_2
{
//cLen指明pCmd指向的缓冲区大小
int cLen;
char *pCmd;
};
#pragma pack(pop)
这个结构体描述了一个简单的网络数据包,而他的长度是不定长的!是不是觉得比较奇怪,这里定义一个char cmd[0]是什么意思、又有什么意义呢?
答案是在这个结构体定义了一个字符数组,他的长度(开销)是0个字节!也就是说sizeof(cmd)为0。
这样写的意义在于表示这个结构体是不定长的,而且要为该结构体分配内存的时候应该要从堆里动态申请而不能是从栈里分配,简单的说就是只能通过malloc或者new来申请内存缓冲区大小!看下面的例子
//目标缓冲区
char buf_1[]="hello";
//给结构体定长!
size_t pkLen_1=sizeof(_pack_1) + sizeof(buf_1);
//分配堆内存
_pack_1 *pk_1=(_pack_1 *)malloc(pkLen_1);
//设置缓冲区大小
pk_1->cLen=sizeof(buf_1);
//现在访问pk_1->cmd[0] ~ pk_1->cmd[ sizeof(buf_1) - 1 ]都是合法的!
memcpy(pk_1->cmd,buf_1,sizeof(buf_1));
//输出信息
printf("package length is %d/n",pkLen_1);
printf("package's cmd's length is %d/n",pk_1->cLen);
printf("package's cmd content:%s/n",pk_1->cmd);
//注意释放掉所申请的堆内存哦
free(pk_1);
pk_1=NULL;
我们知道,字符数组的数组名是指向其后的缓冲区的首地址,然而我们给该结构体分配内存的时候,多分配了
sizeof(buf_1)个字节,于是现在访问数组名后面的 sizeof(buf_1) - 1 个地址将是合法的!我们把buf1改成指向常量区"My Name is wzoot!!",在不用修改上述代码的情况下,看看输出情况 ^^
这样做是不是很酷?你是否也想到了用字符指针也可以达到一样的目的呢?的确是的,但是考虑下用指针的2个小问题!
首先,一个指针通常是32位的,也就是说,指针本身的开销是4个字节,这比0长度的字符数组开销稍大
其次,如果用指针来表达上述问题,那么还需要一个步骤,那就是要设置指针所指向的缓冲区首地址
即pk_2->pCmd=(char *)pk_2+sizeof(_pack_2);
//目标缓冲区
char buf_2[]="hello";
//给结构体定长!
size_t pkLen_2=sizeof(_pack_2) + sizeof(buf_2);
//分配堆内存
_pack_2 *pk_2=(_pack_2 *)malloc(pkLen_2);
pk_2->cLen=sizeof(buf_2);
//在操作之前,需要给指针赋地址
pk_2->pCmd=(char *)pk_2+sizeof(_pack_2);
//现在访问pk_2->pCmd[0] ~ pk_2->pCmd[ sizeof(buf_2) - 1 ]都是合法的!
memcpy(pk_2->pCmd,buf_2,sizeof(buf_2));
//输出信息
printf("package length is %d/n",pkLen_2);
printf("package's cmd's length is %d/n",pk_2->cLen);
printf("package's cmd content:%s/n",pk_2->pCmd);
//注意释放掉所申请的堆内存哦
free(pk_2);
pk_2=NULL;
这样做既麻烦,又可能导致粗心出错,而利用字符数组多方便,而且安全一点,和乐而不为呢?
//设置字节对齐为1,来反应结构体的真实大小
#pragma pack(push,1)
struct _pack_1
{
//cLen指明cmd指向的缓冲区大小
int cLen;
//在vc中不可以为0,那么设置为1;
char cmd[0];
};
struct _pack_2
{
//cLen指明pCmd指向的缓冲区大小
int cLen;
char *pCmd;
};
#pragma pack(pop)
这个结构体描述了一个简单的网络数据包,而他的长度是不定长的!是不是觉得比较奇怪,这里定义一个char cmd[0]是什么意思、又有什么意义呢?
答案是在这个结构体定义了一个字符数组,他的长度(开销)是0个字节!也就是说sizeof(cmd)为0。
这样写的意义在于表示这个结构体是不定长的,而且要为该结构体分配内存的时候应该要从堆里动态申请而不能是从栈里分配,简单的说就是只能通过malloc或者new来申请内存缓冲区大小!看下面的例子
//目标缓冲区
char buf_1[]="hello";
//给结构体定长!
size_t pkLen_1=sizeof(_pack_1) + sizeof(buf_1);
//分配堆内存
_pack_1 *pk_1=(_pack_1 *)malloc(pkLen_1);
//设置缓冲区大小
pk_1->cLen=sizeof(buf_1);
//现在访问pk_1->cmd[0] ~ pk_1->cmd[ sizeof(buf_1) - 1 ]都是合法的!
memcpy(pk_1->cmd,buf_1,sizeof(buf_1));
//输出信息
printf("package length is %d/n",pkLen_1);
printf("package's cmd's length is %d/n",pk_1->cLen);
printf("package's cmd content:%s/n",pk_1->cmd);
//注意释放掉所申请的堆内存哦
free(pk_1);
pk_1=NULL;
我们知道,字符数组的数组名是指向其后的缓冲区的首地址,然而我们给该结构体分配内存的时候,多分配了
sizeof(buf_1)个字节,于是现在访问数组名后面的 sizeof(buf_1) - 1 个地址将是合法的!我们把buf1改成指向常量区"My Name is wzoot!!",在不用修改上述代码的情况下,看看输出情况 ^^
这样做是不是很酷?你是否也想到了用字符指针也可以达到一样的目的呢?的确是的,但是考虑下用指针的2个小问题!
首先,一个指针通常是32位的,也就是说,指针本身的开销是4个字节,这比0长度的字符数组开销稍大
其次,如果用指针来表达上述问题,那么还需要一个步骤,那就是要设置指针所指向的缓冲区首地址
即pk_2->pCmd=(char *)pk_2+sizeof(_pack_2);
//目标缓冲区
char buf_2[]="hello";
//给结构体定长!
size_t pkLen_2=sizeof(_pack_2) + sizeof(buf_2);
//分配堆内存
_pack_2 *pk_2=(_pack_2 *)malloc(pkLen_2);
pk_2->cLen=sizeof(buf_2);
//在操作之前,需要给指针赋地址
pk_2->pCmd=(char *)pk_2+sizeof(_pack_2);
//现在访问pk_2->pCmd[0] ~ pk_2->pCmd[ sizeof(buf_2) - 1 ]都是合法的!
memcpy(pk_2->pCmd,buf_2,sizeof(buf_2));
//输出信息
printf("package length is %d/n",pkLen_2);
printf("package's cmd's length is %d/n",pk_2->cLen);
printf("package's cmd content:%s/n",pk_2->pCmd);
//注意释放掉所申请的堆内存哦
free(pk_2);
pk_2=NULL;
这样做既麻烦,又可能导致粗心出错,而利用字符数组多方便,而且安全一点,和乐而不为呢?
相关文章推荐
- C++中将字节数组转换为字符数组的两个方法
- C++中取出的字节数组转为结构
- C++指针、数组和结构
- [C++]字节对齐与结构体大小
- c++字符串和字符数组的比较
- c++关于字符数组
- C/C++中字符指针数组及指向指针的指针的含义
- C++基础之字符数组和字符串
- 字节数组和字符之间互换
- C#中结构数组怎么定义?怎么获取一个字符的ASCII码?
- 如何替换字符数组中的 某些字符? C/C++
- C\C++常用字符串\字符数组处理函数汇总
- java二进制,字节数组,字符,十六进制,BCD编码转换
- C++基础之字符数组和字符串
- 【字符串】NOI--ch0107--02--找第一个只出现一次的字符(指针数组,有技巧)
- 各自字符 字节 数组转换;
- 学习札记: C++指向字符数组的指针
- [C++ Primer Plus]学习笔记--关于C++ string和c类型字符数组的对比
- 结构体内字节手动对齐(#pragam pack)
- 《C和指针》学习笔记五/数组、字符串字符和字节/