c99柔性数组

Posted jacc.kim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c99柔性数组相关的知识,希望对你有一定的参考价值。

变长结构体

1 struct test
2 {
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 test
11 {
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;   // 此处输出 4
35 
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 }

参考文献:

以上是关于c99柔性数组的主要内容,如果未能解决你的问题,请参考以下文章

linux-柔性数组

柔性数组的介绍和简单使用

变长数组的使用

柔性数组在实际项目中的应用?

柔性数组在实际项目中的应用?

柔性数组在实际项目中的应用?