John Bollinger所写的是一种巧妙利用结构体和内存工作方式的方法,但这也是一种容易导致段错误的方法(想象一下分配一个 Person
数组,然后稍后将最后一个元素传递给访问其ID或名称的“方法”),或者损坏数据(在 Person
数组中,下一个 Person
正在覆盖前一个 Person
的“私有”变量)。您必须记住,必须创建指向 Person
的指针数组,而不是 Person
数组(这听起来很明显,直到您决定优化某些东西,并认为您可以比初始化函数更有效地分配和初始化结构体)。
不要误解,这是一个解决问题的好方法,但在使用时必须小心。我建议(虽然每个
Person
会使用4/8字节更多的内存),创建一个结构体
Person
,其中包含一个指向另一个结构体的指针,该结构体仅在.c文件中定义并保存私有数据。这样做会更难出现错误(如果是一个更大的项目,相信我 - 您迟早会犯错)。
.h 文件:
#pragma once
#define NAME_MAX_LEN 20
typedef struct _person {
float wage;
int groupid;
_personPriv *const priv;
} Person;
void personInit(Person *p, const char *name);
Person* personNew(const char *name);
const char const *getName (Person *p);
int getId (Person *p);
.c 文件:
typedef struct {
int id;
char name[NAME_MAX_LEN];
} _personPriv;
const char const *getName (Person *p) {
return p->priv->name;
}
int getId (Person *p) {
return p->priv->id;
}
_personPriv* _personPrivNew(const char *name) {
_personPriv *ret = memcpy(
malloc(sizeof(*ret->priv)),
&(_personPriv) {
.id = generateId();
},
sizeof(*ret->priv)
);
strncpy(ret->name, name, strlen(name));
return ret;
}
void personInit(Person *p, const char *name) {
if(p == NULL)
return;
p->priv = memcpy(
malloc(sizeof(*p->priv)),
&(_personPriv) {
.id = generateId();
},
sizeof(*p->priv)
);
ret->priv = _personPrivNew(name);
if(ret->priv == NULL) {
}
}
Person* personNew(const char *name) {
Person *ret = malloc(sizeof(*ret));
ret->priv = _personPrivNew(name);
if(ret->priv == NULL) {
free(ret);
return NULL;
}
return ret;
}
顺便提一下:可以实现这个版本,使得私有块在结构体的“公共”部分之后/之前分配,以改善局部性。只需分配sizeof(Person) + sizeof(_personPriv)
并初始化一个部分为Person
,另一个部分为_personPriv
。
id
和name
)不被编辑? - Wootiae