zoukankan      html  css  js  c++  java
  • 变长结构体

    变长结构体

    变长结构体是由gcc扩展的一种技术,它是指其最后一个成员的长度不固定flexible array member,也叫柔性数组,先来看一个简单的例子:

    #include <stdlib.h>
    #include <stdio.h>
    
    #pragma pack(1)
    typedef struct {
        int a;
        char b[10];
        char *vector;         
    } cq; 
    #pragma pack()
    
    int main()
    {
        cq *a = malloc(sizeof(cq));
    
        char str[] = "hello";
    
        a->vector = malloc(sizeof(str));
        memcpy(a->vector, str, sizeof(str));
    
        printf("%s
    ", a->vector);       // "hello"
        printf("%d
    ", sizeof(cq));      // 22
    
        free(a->vector);
        free(a);
    
        return 0;
    }

    这段代码中,结构体cq中的成员vector是一个指针,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)。

    而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,一次释放。而使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。其次,就是分配一段连续的的内存,减少内存的碎片化。

    #include <stdlib.h>
    #include <stdio.h>
    
    #pragma pack(1)
    typedef struct {
        int a;
        char b[10];
        char vector[0];         // 可变数组
    } cq; 
    #pragma pack()
    
    int main()
    {
        char str[] = "hello";
    
        cq *a = malloc(sizeof(cq) + sizeof(str));   // decide amount used
        memcpy(a->vector, str, sizeof(str));
    
        printf("%s
    ", a->vector);       // "hello"
        printf("%d
    ", sizeof(cq));      // 14
    
        free(a);
    
        return 0;
    }

    例子中,打印出的结构体长度是14(为成员a和b的长度之和),——变长数组vector不占结构体的空间!

    可见,变长结构体是能让我们在分配时再决定其大小,而不是在定义时就要固定其数组长度。

    可变数组的一种更通用的用法是用一个成员指明变长数组的长度,方便在其他地方读取数组内容。

    struct line {
       int length;
       char contents[0];
    };
    
    struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
    thisline->length = this_length;

    最后,转述一段C99标准(draft N1570)对这个问题的描述,本人英文很烂,就不翻译了。

    As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

    参考:

    http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct

  • 相关阅读:
    hibernate关联关系
    数据结构之二叉树java实现
    队列java实现
    栈java实现
    原生JS结合cookie实现商品评分组件
    JAVA学习第一阶段(2)
    JAVA学习第一阶段(1)
    如何修改hosts并保存
    运行Apache时出现the requested operation has failed
    实现一元多项式
  • 原文地址:https://www.cnblogs.com/chenny7/p/3657712.html
Copyright © 2011-2022 走看看