仅访问结构的某些成员,而不是全部访问

时间:2018-11-12 09:39:53

标签: c struct

我目前有一个结构,其中有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); } ,而不是传递readStructwriteStruct。对于if条件,我只能通过genericStruct,这样就可以正常工作,但是,我不知道在else条件中要通过什么。

我只想在else条件下传递该结构的前5个成员。我该怎么办?

2 个答案:

答案 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.afoo.write.afoo.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);

任何时候只要要写入该结构,都只能使用该函数。