zoukankan      html  css  js  c++  java
  • 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] = '';
    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 }

    参考文献:

  • 相关阅读:
    iOS开发之巧用Block和代理方法结合来传值
    iOS开发之Bug--UITextField使用时文字向下偏移问题
    iOS开发之开源项目链接
    IOS开发之Bug--iOS7View被导航栏遮挡问题的解决
    Android开发--异步加载
    添加 All Exceptions 断点后, 每次运行都会在 main.m 中断的一种解决方法
    IOS开发之Bug--遇到一个类型不确定的bug
    iOS开发之功能模块--计算高度Demo探究手稿
    IOS开发之Bug--View是懒加载导致出误以为是UI加载的bug
    iOS中的round/ceil/floorf函数略解
  • 原文地址:https://www.cnblogs.com/tongy0/p/6513979.html
Copyright © 2011-2022 走看看