首页 > 代码库 > c99柔性数组

c99柔性数组

变长结构体

1 struct test2 {3     int     nSize;4     char    data[];    // 或者 char data[0];但建议使用 char data[]; 注意:c98 时不支持柔性数组,其仅作为非标准扩展。到c99时纳入标准5 };

如上面代码即为一变长结构体,其中 char data[]; 为一变长数组,称之为柔性数组。正是因其为变长数组,故结构体才可变长。使用 test 结构体时,可用 malloc 申请大于 sizeof(test) 长度的空间。如下:

 1     const auto nSizeTest    = sizeof(test); 2     const auto nExtraSize   = 3 * (sizeof(char)); 3  4     test* stpTest           = (test*)malloc(nSizeTest + nExtraSize); 5  6     stpTest->nSize          = nSizeTest + nExtraSize; 7     memset((void*)stpTest->data, 0x0L, nExtraSize); 8     const auto nTempLen     = strlen(stpTest->data); 9     for (auto nIndex = 0; nIndex < nExtraSize - 1; ++nIndex) {10         stpTest->data[nIndex] = char(96 + nIndex);11     }12     stpTest->data[nExtraSize - 1] = \0;13 14     // some code here........15 16     free(stpTest);          // 此处 free 的是刚才所申请的全部内存空间17     stpTest = nullptr;

使用柔性数组有以下几个好处:

  • 首先柔性数组不占内存,值代表地址;
  • 可以通过stpTest->data来访问字符串,符合常规用法。
  • 字符串长度为动态分配。

关于柔性数组的注意点:

  1. 柔性数组只能放置于结构体的末尾声明
  2. 由于柔性数组是动态可变长的,则一般情况下只会用在没有继承关系、没有虚表的变长结构体(或类中)中,如果有继承关系的或虚表,则后果将非常严重。(有看过对象模型的人,肯定清楚为什么,此处就不多说)
  3. 上面变长结构体中的柔性数组除了 char 型别外,还可以是其他任何类型,甚至是自定义的类类型。但是:如果是自定义的类类型,则需要自己手动调用构造与析构。因为 malloc 与 free 时,不会自动调用构造与析构。从而可能导致不可预知的结果,以及内存泄漏的可能。比如:
 1 class obj 2 { 3 public: 4     int nIndex; 5     ~obj() { 6         std::cout << "obj " << nIndex << " destroy" << std::endl; 7     } 8 }; 9 10 struct test11 {12     int nSize;13     obj data[];14 };15 16 int _tmain(int argc, _TCHAR* argv[])17 {18 19     const auto nSizeTest = sizeof(test);20     const auto nExtraSize = 3 * (sizeof(obj));21 22     test* stpTest = (test*)malloc(nSizeTest + nExtraSize);23 24     stpTest->nSize = nSizeTest + nExtraSize;25     memset((void*)stpTest->data, 0x0L, nExtraSize);26     for (auto nIndex = 0; nIndex < 3; ++nIndex) {27         stpTest->data[nIndex].nIndex = nIndex + 1;28     }29 30     auto nSize = sizeof(test);31     std::cout << "sizeof(test) = " << nSize << std::endl;       // 此处输出 4.说明柔性数组并不会占用 test 的空间.32 33     nSize = sizeof(*stpTest);34     std::cout << "sizeof(*stpTest) = " << nSize << std::endl;   // 此处输出 435 36     obj* ptr = stpTest->data;37 38     free(stpTest);      // 此处将释放前面所申请的全部空间,但是:不会调用 ~obj() 函数!!!39     stpTest = nullptr;40 41     //ptr->nIndex = 777;  // 如果调用此句会蹦,因为前面 free 时已经全部释放掉所申请空间了,包括柔性数组 data 的那3个 obj 对象的空间42 43     system("pause");44 45     return 0;46 }

参考文献:

  • http://luodw.cc/2015/10/22/Cplus6/
  • http://blog.csdn.net/ce123_zhouwei/article/details/8973073

c99柔性数组