• 关于柔性数组的一些问题


    转自:http://blog.csdn.net/irean_lau/article/details/44455879


    关于柔性数组的一些问题


    柔性数组结构成员
      结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其 他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。


    结构体变长的妙用——0个元素的数组
    有时我们需要产生一个结构体,实现了一种可变长度的结构。如何来实现呢?


    看这个结构体的定义:
    typedef struct st_type
    {
    int nCnt;
    int item[0];
    }type_a;
    (有些编译器会报错无法编译可以改成:)
    typedef struct st_type
    {
    int nCnt;
    int item[];
    }type_a;
    这样我们就可以定义一个可变长的结构,用sizeof(type_a)得到的只有4,就是sizeof(nCnt)=sizeof(int)那个0个元素的数组没有占用空间,而后我们可以进行变长操作了。




    C语言
    type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
    C++语言:
    type_a *p = (type_a*)new char[sizeof(type_a)+100*sizeof(int)];
    这样我们就产生了一个长为100的type_a类型的东西用p->item[n]就能简单地访问可变长元素,原理十分简单

    ,分配了比sizeof(type_a)多的内存后int item[];就有了其意义了,它指向的是int nCnt;后面的内容,是没

    有内存需要的,而在分配时多分配的内存就可以由其来操控,是个十分好用的技巧。
    而释放同样简单:
    C语言版:
    free(p);
    C++语言版:
    delete []p;



    最后引一篇“C语言结构体中的成员数组和指针”http://coolshell.cn/articles/11377.html


    -------------------------------------------------------------------------------

    转自:  http://blog.csdn.net/yby4769250/article/details/7294696


    C/C++ 中的0长数组(柔性数组)


    在标准CC++0长数组如charArray[0]是不允许使用的,因为这从语义逻辑上看,是完全没有意义的。

    但是,GUN中却允许使用,而且,很多时候,应用在了变长结构体中,如:

    StructPacket

    {

    Int state;

    Int len;

    Char cData[0]; //这里的0长结构体就为变长结构体提供了非常好的支持

    };

     

    首先对0长数组做一个解释:

    用途 :长度为0的数组的主要用途是为了满足需要变长度的结构体。

    用法 :在一个结构体的最后 ,申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配

     

    请仔细理解后半部分,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

     

    对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

    Struct Buffer

    {

    Int len;

    Char cData[0];

    };

    这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就会浪费1024个字节的空间,也会造成不必要的流量浪费

    Struct packet

    {

        char data[2048];

    }

    packet p;

    memcpy(p.data,"1024 datas.........",1024)

    send(socket,(char*)&p,sizeof(p));

    由于考虑到数据的溢出,变长数据包中的data数组长度一般会设置得足够长足以容纳最大的数据,因此packet中的data数组很多情况下都没有填满数据,因此造成了浪费,而如果我们用变长数组来进行封包的话,就不会造成浪费(最多会造成4个字节的浪费,包头的int型的len不属于数据因此算是浪费),如前面的Buffer结构体,假如我们要发送1024个字节,我们如何构造这个数据包呢:

    char *tmp = (char*)malloc(sizeof(Buffer)+1024) //这句代码的作用是申请一块连续的内存空间,这块内存空间的长度是Buffer的大小加上1024数据的大小,由两部分构成,sizeof(Buffer)和1024,如果仔细观察的话,会发现这种申请方法比第一种多了一段sizeof(Buffer)大小的空间,原因何在?如下

    Buffer *p = (Buffer*)tmp;

    p->len = 1024;

    memcpy(p.cData,"1024 datas............",1024);

    如上三行代码,首先做一个强制类型转换,Buffer类型的指针指向内存的起始位置,这段内存要分两部分使用,前部分4个字节p->len,作为包头(就是多出来的那部分),这个包头是用来描述紧接着包头后面的数据部分的长度,这里是1024,所以前四个字节赋值为1024(既然我们要构造不定长数据包,那么这个包到底有多长呢,因此,我们就必须通过一个变量来表明这个数据包的长度,这就是len的作用),而紧接其后的内存是真正的数据部分,通过p->cData定位到该部分的起始地址,最后,进行一个memcpy()内存拷贝,把要发送的数据填入到这段内存当中,最后:

    send(socket,p,sizeof(Buffer)+1024);发送数据


  • 相关阅读:
    ES 分组排序java实现
    java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?
    Java 虚拟机对锁优化所做的努力
    Docker 核心概念、安装、端口映射及常用操作命令,详细到令人发指。
    20条最最常用的Linux命令讲解
    Linux查看系统配置常用命令
    全面认识Docker和基本指令
    25个深度学习开源数据集
    Docker 简单运用
    一小时学会C# 6
  • 原文地址:https://www.cnblogs.com/alan666/p/8312047.html
Copyright © 2020-2023  润新知