如何定义不定长结构体,及分配空间

发布于 2021-11-18 07:55:46 字数 81 浏览 919 评论 12

    我想要这样一个结构体,其中有的成员可能数目有多个(个数会变化)。如何定义这样一个结构体及如何使用中动态分配内存呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

疑心病 2021-11-24 18:40:23

@gvim ,你说的char p[0],c的iso标准不支持是对的。如果使用 char p[]会存在问题,它需要放在结构体的下部。当我需要在结构体下面扩充成员时,会产生问题。曾经用过p[]的写法。最终还是决定使用char p[0];

我刚才翻了一下我以前的intel c编译器,还没测试过,奶奶的过期了。。对我来说,支持这两个编译器就足够了。哈。

不过我要看我的基础库做完后的情况,如果这个基础结构体下部,可以不增加其他成员,我会采用p[],毕竟如你说的,这样适用面更宽。哈。

凡尘雨 2021-11-24 18:40:23

这个技巧我觉得可以称作结构体的单一继承

//纯手写,可能有错,看下大概意思就好了

struct base {
    char name[5];
    int age;
    double weight;
};

struct emploee {
    struct base;
    int level;
    char department[100];
};

int get_age_x_weight(struct base *b)
{
    return b->age * b->weight;
}

int get_level_x_age_x_weight(struct emploee *e)
{
    //(struct base*)e可以将它转化成它的父结构体的形态
    //这样就能使用父结构体的操作了
    //对于父结构体,struct emploee就是它的一种扩充
    //这个技巧在许多地方都可以用,可以不改变系统接口的同时,
    //夹带私有数据,简化实现,提高性能(不用涉及到运行时的查找算法)
    return e->level * get_age_x_weight((struct base*)e);
}
别低头,皇冠会掉 2021-11-24 18:40:23

@gvim ,你说的char p[0],c的iso标准不支持是对的。如果使用 char p[]会存在问题,它需要放在结构体的下部。当我需要在结构体下面扩充成员时,会产生问题。曾经用过p[]的写法。最终还是决定使用char p[0];

我刚才翻了一下我以前的intel c编译器,还没测试过,奶奶的过期了。。对我来说,支持这两个编译器就足够了。哈。

不过我要看我的基础库做完后的情况,如果这个基础结构体下部,可以不增加其他成员,我会采用p[],毕竟如你说的,这样适用面更宽。哈。

不乱于心 2021-11-24 18:40:23

@gvim ,你说的char p[0],c的iso标准不支持是对的。如果使用 char p[]会存在问题,它需要放在结构体的下部。当我需要在结构体下面扩充成员时,会产生问题。曾经用过p[]的写法。最终还是决定使用char p[0];

我刚才翻了一下我以前的intel c编译器,还没测试过,奶奶的过期了。。对我来说,支持这两个编译器就足够了。哈。

不过我要看我的基础库做完后的情况,如果这个基础结构体下部,可以不增加其他成员,我会采用p[],毕竟如你说的,这样适用面更宽。哈。

如此安好 2021-11-24 18:40:22

谢谢~

浮生未歇 2021-11-24 18:40:20
struct cd {
    int ab;
    char a[];
};

int main()
{
    struct cd *cd;
    cd = (struct cd *)malloc(sizeof(struct cd) + 1024);
    cd->ab = 2;
    cd->a[0] = 'a';
    cd->a[1] = 'b';

    return 0;
}

@Mallon 指针 和  char[] 的差别一是需要多一个域来放指针,二是char[]只是符号,因此分配出来的内存和头部是连续的,而指针的分配是一个和头部不连续地址的。第二种情况在计算校验的时候很方便,不管头部怎么设计怎么变,只要把这段地址做为连续内存遍历即可,或者做数据包的时候。

草莓味的萝莉 2021-11-24 18:40:13

99标准用 char p[]吧,0长度数组标准不支持,只是gcc的扩展,有些编译器不支持这个扩展。gcc用-pedantic会有警告的。

沙与沫 2021-11-24 18:39:59

回复
你说的这个情况我重新看了标准,确实如此。不过暂时不动。哈。

命硬 2021-11-24 18:39:51

谢谢~^_^

贱贱哒 2021-11-22 16:32:57

贴段代码给你,这个是我自己写的基本库里的代码,看你是否能理解,你注意,p[0] ,和hp的用法,在_setP的宏里有定义,实际申请到的空间,返回的位置会空出一段,给另外个结构体。通过_Pheader的宏,可以访问到。这里先补充几个类型的定义

#define _CONST_UT(_T_,n) typedef const unsigned _T_ _uc##n;
#define _CONST_ST(_T_,n) typedef const signed _T_ _ic##n;
#define _UNSIGNED_T(_T_,n) typedef unsigned _T_ _u##n; _CONST_UT(_T_,n);
#define _SIGNED_T(_T_,n) typedef signed _T_ _i##n; _CONST_ST(_T_,n);
#define _CREATE_T(_T_,n) _UNSIGNED_T(_T_,n) _SIGNED_T(_T_,n)
_CREATE_T(char,8)
//typedef signed char _i8;
//typedef const signed char _ic8;
//typedef unsigned char _u8;
//typedef const unsigned char _uc8;
_CREATE_T(short,16)
_CREATE_T(int,32)
_CREATE_T(long long,64)
typedef _u8 * _p;//byte point

typedef _u32 _I;// memory space size  & index

typedef _u64 _PI;// the point type 2 interger type , i386 need typedef _u32 _PI;


#define _p2I(p)	(_PI)(p) //get p address change to interger..
typedef struct {
	//_i64 pheader[0];
	_p hp;//header base p;
	_I ns;// ns * us == s
	_I t;//tail not used
	_I h;//head not used
	_I n;// data unit num
	_I us; // unit size
	_I s;//size
	_u8 p[0];//have bug if used BUS_S a[10];;so not allow used array mode
}_D_BUF;
typedef _D_BUF * _P;

#define _SIZE(Q) (Q)->s
#define _HEAD(Q) (Q)->h
#define _TAIL(Q) (Q)->t
#define _NUM(Q) (Q)->n
#define _UNITS(Q) (Q)->us
#define _UNIT_NUM(Q) (Q)->ns
#define _sizeP(hs,s)  (_salign8(hs) +  _salign8(s) + _salign8(sizeof(_D_BUF)))

#define _initP(P,ns,us) do {_bug(ns == 0);
 _UNITS(P) = ((us) == 0)? 1 : (us);
 _UNIT_NUM(P) = ns;
 _SIZE(P) = _UNIT_NUM(P) * _UNITS(P);  _HEAD(P) = 0; _TAIL(P) = 0;
_NUM(P) = 0;
}while (0)
//op to _P
#define _Pheader(P,_T_) ((_T_*)((P)->hp))

#define _setP(P,_ph,header_size,unit_num,unit_s) do {
	P = (_P)(_ph+header_size); 
	_initP(P,unit_num,unit_s);
	(P)->hp = (_p)(_ph);
} while (0) //init all 


static _P m_alloc(_I ns,_I hs,_I us,_cs usr,_cs maker){
	
	_I s = ns * us;
	_P pre = 0;
	_p p;
	_error(check_alloc_tab((_p)0) == ss_alloc->buf_size,c_m_alloc_EXIT,
		"%s maker:%s :usr:%s ",error_str[ERR_ALLOC_OVERFLOW],maker,usr);
	_bug(s == 0);
	p = (_p)malloc(_sizeP(hs,s));//sizeof(_D_BUF)+s + hs);
	
	_bug(_p2I(p) & 0x7);
	ss_alloc->alloc_buf[ss_alloc->buf_bias].p = p;
	ss_alloc->alloc_buf[ss_alloc->buf_bias].maker = maker;
	ss_alloc->alloc_buf[ss_alloc->buf_bias].usr = usr;	

	_setP(pre,p,hs,ns,us);

c_m_alloc_EXIT:
	return pre;
}
毁梦 2021-11-19 05:29:41

基本思路:

  1. 定义结构体。不定长部分用指针,当然如果能固定最大长度而且不太长的话数组也可以
  2. 定义针对该结构体的分配和释放函数,例如struct xxx * alloc_xxx(参数...),void free_xxx(struct xxx * p)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文