当前位置: 首页 > 图灵资讯 > 技术篇> C/C++中的变长结构体

C/C++中的变长结构体

来源:图灵教育
时间:2023-06-15 09:32:36

1. 问题来源

首先,看下面的代码:

#include <stdlib.h>#include <stdio.h>#include <string.h>#define MAX_LEN 1024typedeffetefedefeftefed struct KDtree{    double data[MAX_LEN]; // 数据    int dim; // 选择的维度    struct KDtree *left; // 左子树    struct KDtree *right; // 右子树}kdtree_node;int main(){    kdtree_node *kd_node = (kdtree_node *)malloc(sizeof(kdtree_node));    printf("kdtree_node: %ld\n", sizeof(kdtree_node)); // 8216    printf("kd_node: %ld\n", sizeof(kd_node));    free(kd_node);    return 0;}

在这个代码中,为了存储数据,最大长度为1024的double数组被申请。如果数据的长度远小于MAX_LEN,这种写法是浪费空间的。

2. 解决的方法

在C语言中有以下构建方法:

struct mumble {//stuffchar pc[];    };

这种最后一个成员长度不固定的写作方法称为柔性数组,也称为伸缩数组,即变长数组。也就是说,当声明结构时,不指定声明数组的大小,并根据具体情况申请足够的空间。

#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct mytest{int a;double b;int c[];  //c不占用空间,只作为符号地址存在,它必须是结构体的最后一个成员}mt;int main(){    printf("mt: %ld\n", sizeof(mt));  // 16int t[10] = {0,1,2,3,4,5,6,7,89};mt* pmt = (mt*)malloc(sizeof(mt) + sizeof(int)*10 + 1);    int i = 0;    if (NULL != pmt){        pmt->a = 1;        pmt->b = 11;        for (i = 0; i < 10; i++) {            (pmt->c)[i] = t[i];        }    }    free(pmt);    return 0;}

至于这里的sizeoff,(mt)为什么是16,涉及到sizeof计算结构体时的地址对齐。意思:柔性数组只能是结构体的最后一个成员。

参考文献
  • 柔性数组-阅读深度探索C++对象模型