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 " 外,程序也可以正确运行.

  • 相关阅读:
    某个牛人做WINDOWS系统文件详解
    常用ASP脚本程序集锦
    LINUX基础:文件安全与权限
    proftpd+mysql+quota
    apache2.0.49tomcat5.0.19jk2建立virtualHost
    URL Redirection(转) Anny
    顶级域名后缀列表(转) Anny
    \u4E00\u9FA5意义 Anny
    How to POST Form Data Using Ruby(转) Anny
    How to get rid of 'Enter password to unlock your login keyring' in Ubuntu(转) Anny
  • 原文地址:https://www.cnblogs.com/tangxin-blog/p/5560699.html
Copyright © 2011-2022 走看看