我现在有一个需要使用8个成员的结构。
typedef struct Foo_s
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
uint16_t f;
uint32_t g;
uint32_t h;
} Foo_s;
这个结构有两个用例,read和write,read使用所有8个成员,write只使用前5个(a-e)。
目前,我已经将其分为两个单独的结构,一个用于读取(有8个成员)和一个用于写入(有5个成员),但是有人建议我可以同时使用一个结构,并且在传递“写入”功能所需的成员时,只访问前5个成员。
if(x == y){
BarRead(&readStruct);
} else {
BarWrite(&writeStruct);
}
与其传递
readStruct
和writeStruct
,不如只使用一个结构genericStruct
。对于if条件,我可以通过&genericStruct
,这将很好,但是,我不知道在else条件下通过什么。我只想在else条件下传递结构的前5个成员。我该怎么做?
最佳答案
如果隐藏在私有封装之后,可以将结构本身声明为任何形式。这将是一个选项:只允许通过setters/getter访问结构。
假设您定义了两个这样的结构:
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
} foo_write_t;
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
uint16_t f;
uint32_t g;
uint32_t h;
} foo_read_t;
然后,您可以创建一个新的ADT,其中包含两个重叠的元素。A
union
,例如:union foo_t
{
foo_write_t write;
foo_read_t read;
struct // C11 anonymous struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
uint16_t f;
uint32_t g;
uint32_t h;
};
};
现在上面有三种不同的方法来访问相同的内存。
foo.a
、foo.write.a
或foo.read.a
。但是,foo.write
缺少f,g,h。如果我们添加私有封装,我们还可以阻止对foo.a
的直接访问。在C语言中,私有封装是通过不透明类型完成的,头“foo.h”变成如下:
// foo.h
typedef union foo_t foo_t;
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
} foo_write_t;
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
uint16_t f;
uint32_t g;
uint32_t h;
} foo_read_t;
foo_t* foo_init(
uint8_t a,
uint8_t b,
uint8_t c,
uint16_t d,
uint8_t e,
uint16_t f,
uint32_t g,
uint32_t h);
void foo_delete (foo_t* foo);
以及相应的c文件:
// foo.c
#include "foo.h"
union foo_t
{
foo_write_t write;
foo_read_t read;
struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint8_t e;
uint16_t f;
uint32_t g;
uint32_t h;
};
};
foo_t* foo_init(
uint8_t a,
uint8_t b,
uint8_t c,
uint16_t d,
uint8_t e,
uint16_t f,
uint32_t g,
uint32_t h)
{
foo_t* foo = malloc(sizeof *foo);
if(foo==NULL)
{
return NULL;
}
foo->a = a;
foo->b = b;
foo->c = c;
foo->d = d;
foo->e = e;
foo->f = f;
foo->g = g;
foo->h = h;
return foo;
}
void foo_delete (foo_t* foo)
{
free(foo);
}
然后可以通过setters/getter提供访问。或者只允许硬拷贝,比如:
void foo_write (foo_t* foo, const foo_write_t* foo_w)
{
memcpy(foo, foo_w, sizeof foo->write);
}
void foo_read (const foo_t* foo, foo_read_t* foo_r)
{
memcpy(foo_r, foo, sizeof foo->read);
}
或者允许调用者直接写入ADT,方法是将地址公开并返回到结构的相关部分:
foo_write_t* foo_get_write (foo_t* foo)
{
return &foo->write;
}
const foo_read_t* foo_get_read (foo_t* foo)
{
return &foo->read;
}
关于c - 仅访问结构的某些成员,而不是全部访问,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53259385/