Chinaunix首页 | 论坛 | 博客
  • 博客访问: 110780
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-22 17:28
文章分类

全部博文(40)

文章存档

2021年(2)

2018年(3)

2017年(29)

2016年(6)

我的朋友

分类: C/C++

2017-04-12 18:07:01

最近,工作时看了别人的代码,有个chance接触这个0数组的使用。代码中要实现类似这么个功能:
内存中有一段缓存区buf,buf前8字节存俩个int型值,接着是一段字符串:

char buf[100];
memset(buf, 0, 100);
int id = 9;
int len = 10;
char msg[] = "123456";

memcpy(buf, &id, 4);
memcpy(buf+4, &len, 4);
memcpy(buf+8, msg, strlen(msg));

另外,有个结构体定义如下:(别人定义的)
struct ss_t{
    int s_id;
    int len;
    char *msg;
};

代码中,有类似下面的一段:
struct ss_t *st;
...
st = (struct ss_t *)buf;

将buf强制转换成struct ss_t类型。

然后对st操作:

当对st->msg操作时,出错。
    printf("%s\n", st->msg);   
显然,这边msg只是一个指针,指针的指向不知道,所以就出错了。我开始的解决办法是抛
弃这个结构体直接对buf进行操作,改动颇大。后来,想想,能不能改动小点。记得之前听过别人说C语言的0数组,就试试了。把结构体的定义换成:
struct ss_t{
    int s_id;
    int len;
    char msg[0];
};

然后再编译运行,正常工作。其实,结构体对0数组时没有分配空间的,但是,相当于定义了一个数组,数组没有元素,但是,数组的首地址又是刚好在len之后。引用msg,就相当于对那块地址操作了。所以,问题顺利解决。
此时,sizeof(struct ss_t) = 8;

另外,把其中的0去掉,定义成如下:
struct ss_t{
    int s_id;
    int len;
    char msg[];
};
程序还是照常运行。
此时,sizeof(struct ss_t) = 8。
可见,有没有0俩者一样,而且运行效果也一样。

这里,msg相当于一个常量指针.不过, 读取st->msg:

printf("%s", st->msg);输出123456

ok,成功了


我写的一个完整例子:
#include
#include

#define INT_LEN sizeof(int)
struct ss_t{
    int s_id;
    int len;
    char msg[];
};

int main(void)
{
    int id;
    int len;
    char msg[] = "123456";
    char *buf;
    struct ss_t *st;
   
    buf = (char *)malloc(sizeof(char) * 100);
    if (buf == NULL) {
        return 1;
    }
    memset(buf, 0, 100);
   
    id = 65;
    len = 66;
    memcpy(buf, &id, INT_LEN);
    memcpy(buf + INT_LEN, &len, INT_LEN);
    memcpy(buf + 2 * INT_LEN, msg, strlen(msg));  
    st = (struct ss_t *)buf;
   
    printf("st->s_id %d st->len %d\n", st->s_id, st->len);
    printf("st->msg %s\n", st->msg+1);   
   
    return 0;
}



阅读(1224) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~