我目前有一个结构,其中有8个成员需要使用。
print (at)
此结构有两个用例:读取和写入,其中读取使用所有8个成员,而写入仅使用前5个(a-e)。
当前,我将其分为两个单独的结构,一个用于读取(具有8个成员)和一个用于写入(具有5个成员),但是建议我可以对两个都使用一个结构,并且在传递所需的成员时的“写入”功能只能访问前5个成员。
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;
我只想使用一个结构if(x == y){
BarRead(&readStruct);
} else {
BarWrite(&writeStruct);
}
,而不是传递readStruct
和writeStruct
。对于if条件,我只能通过genericStruct
,这样就可以正常工作,但是,我不知道在else条件中要通过什么。
我只想在else条件下传递该结构的前5个成员。我该怎么办?
答案 0 :(得分:3)
如果将结构本身隐藏在私有封装后面,则可以将其声明为任何内容。这将是一种选择:只允许通过setters / getters访问结构。
假设您定义了两个这样的结构:
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,其中包含两个元素,并且元素重叠。 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;
};
};
上面提供了3种不同的方式来访问相同的内存。 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);
}
然后,您可以通过设置器/获取器提供访问权限。要么只允许打印纸,像这样:
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;
}
答案 1 :(得分:0)
您可以为仅包含a到e的结构创建typedef
。然后,您可以定义一个“插入数据”函数,该函数将指向该类型结构的指针作为参数。
void Insert_Data(aToEStruct *data);
任何时候只要要写入该结构,都只能使用该函数。