zoukankan      html  css  js  c++  java
  • C/C++ 中长度为0的数组

    参考文献:http://blog.csdn.net/zhaqiwen/article/details/7904515

    近日在看项目中的框架代码时,发现了了一个奇特的语法:长度为0的数组例如 

     uint8_t buf[0]; 

    我从未见过这样的写法,所以在网上查了查资料,了解并记录下来.

    在标准的C/C++中,长度为0的数组是不被允许的,它算是一个C/C++扩展,如果你的编译器支持这个扩展,你就可以使用它.

    VS系列编译器不完全支持这个扩展,如果你这样定义,多半会在编译时出现这样的警告:warning C4200: 使用了非标准扩展 : 结构/联合中的零大小数组,当 UDT 包含大小为零的数组时,无法生成复制构造函数或副本赋值运算符

    GUN编译器完全支持这个扩展,你可以合法的声明长度为0的数组,但这种声明的最典型的用法就是位于数组中的最后一项,为了方便内存缓冲区的管理,例如:

    struct Line{
        uint32_t length;
        char contents[0];
    };

     在结构体中,长度为0的数组不会占用存储空间 ,在上述例子中 sizeof(Line)=4

    在申请内存空间时,缓冲区的空间可以和结构体的空间一起申请,一次操作就可以完成.例如

    uint32_t length = 10;
    struct Line *pLine = (struct Line *)malloc(sizeof (struct Line) + length);
    pLine->length = length;

    上述代码就动态地为结构体申请了长度(length)为10byte的缓冲区,而且由于是同一次malloc操作,缓冲区与结构体的内存地址是连续的,而且可以按照数组下标访问缓冲区元素,例如

    for(uint32_t i = 0;i < pLine->length;++i)
    {
        pLine->contents[i] = i;
    }

    由于缓冲区与结构体的内存地址是连续的,在释放内存的时候,只需要一次free操作.

    综上所述,比起在结构体中定义一个指针指向另一片缓冲区地址的做法,使用长度为0的数组有以下好处:

    1->指针本身需要占用内存,而长度为0的数组不需要

    2->长度为0的数组定义出的缓冲区可以和结构体处在同一片连续地址中,只要一次malloc操作和free操作.如果用指针,需要分别申请和释放结构体内存和指针指向的内存块,至少需要两次以上的内存操作.

    测试代码:

    编译器:  gcc version 4.8.1 (tdm-2)

    #include <stdio.h>
    #include <stdint.h>
    #include <malloc.h>
    struct Line{
        uint32_t length;
        uint8_t contents[0];
    };
    int32_t main()
    {
        uint32_t length = 10, i;
        printf("sizeof(Line)=%d
    ", sizeof(struct Line));
        struct Line *pLine = (struct Line *)malloc(sizeof (struct Line) + length);
        pLine->length = length;
        for (i = 0; i < pLine->length; ++i)
        {
            pLine->contents[i] = i;
        }
        for (i = 0; i < pLine->length; ++i)
        {
            printf("i=%d,contents[i]=%d
    ", i, pLine->contents[i]);
        }
        //free(pLine);
        return 0;
    }

    成功执行并打印结果:

    sizeof(Line)=4
    i=0,contents[i]=0
    i=1,contents[i]=1
    i=2,contents[i]=2
    i=3,contents[i]=3
    i=4,contents[i]=4
    i=5,contents[i]=5
    i=6,contents[i]=6
    i=7,contents[i]=7
    i=8,contents[i]=8
    i=9,contents[i]=9
    Press any key to continue . . .

    在VS2013中编译运行上述代码,除了会报警告 " warning C4200 " 外,程序也可以正确运行.

  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/tangxin-blog/p/5560699.html
Copyright © 2011-2022 走看看