Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 封装对类似结构的访问_C - Fatal编程技术网

C 封装对类似结构的访问

C 封装对类似结构的访问,c,C,我的应用程序是用C语言编写的。我有一个模块,它使用来自某个给定全局结构的一些数据。现在,我必须扩展模块,以可选地针对不同的给定全局结构工作,该结构基本上提供相同的字段(就我的模块而言),但名称不同 这里有一个汽车类比,希望能让我的问题更清楚。我有两个我无法控制的全球结构 struct { unsigned char manufacturer_id; unsigned short top_speed; } Car; struct { RGB_t color; unsign

我的应用程序是用C语言编写的。我有一个模块,它使用来自某个给定全局结构的一些数据。现在,我必须扩展模块,以可选地针对不同的给定全局结构工作,该结构基本上提供相同的字段(就我的模块而言),但名称不同

这里有一个汽车类比,希望能让我的问题更清楚。我有两个我无法控制的全球结构

struct {
   unsigned char manufacturer_id;
   unsigned short top_speed;
} Car;

struct {
   RGB_t color;
   unsigned short topSpeed;
   unsigned char mfr;
} Automobile;
假设我的汽车管理器模块使用来自汽车的信息。例如:

const char *car_manager__get_manufacturer_name(car_manager_t *self)
{
    return self->manufacturers[Automobile.mfr];
}
我想将Car Manager扩展为可选(可能由Car\u Manager\u t实例中的标志决定)使用来自Car的相同信息,因此上述函数将返回
self->manufacturers[Car.manufacturer\u id]
。我不想在添加此功能时复制模块中的任何逻辑


我想我必须在访问全局结构时设置一个接口。有什么建议吗?

我不知道您到底需要什么,但请注意,如果您有一个联合,其中包含多个以相同类型开头的结构,您可以通过所有结构平等地访问这些类型。例如,如果您有:

union bla {
 struct {
  int a;
  char b;
  float *c;
 } s1;
 struct {
  int r;
  char c;
  float *j;
  short s;
 } s2;
 int i;
} un;
然后
un.s1.a
un.s2.r
un.i
是相同的,依此类推
un.s1.c==un.s2.j


也可以考虑移到C++ +/C>(和结构的重载函数)

这只是我脑海中的第一个解决方案,但是一个方法是将你的模块推广到可配置的,这样你就可以告诉它如何查找字段。

自从我在C中编码已经有一段时间了,所以考虑这个伪代码;) 这两个结构:

/* Struct layout 1 */
struct {
    float x; /*aka foo*/
    float y; /*aka bar*/
    float z; /*aka baz*/
} entity_type1;

/* Struct layout 2 */
struct {
    float c; /*aka baz*/
    float a; /*aka foo*/
    float b; /*aka bar*/
} entity_type2;
模块:

struct {
    int foo_index;
    int bar_index;
    int baz_index;
} fields_definition;

/* Private configuration */
fields_definition entity_fields;

/* Private getters */
float foo(void * entity) {
    return *(float*)(entity_ptr + entity_fields.foo_index);
}
float bar(void * entity) {
    return *(float*)(entity_ptr + entity_fields.bar_index);
}
/* Private setters */
void baz(void * entity, float value) {
    *(float*)(entity_ptr + entity_fields.baz_index) = value; /* Legal?? */
}

/* Exported/Public function for setup */
void configure(fields_definition entity_fields_config){
    entity_fields = entity_fields_config;
}

/* Normal exported/public function for usage */
void some_operation(void * entity) {
    baz(entity, foo(entity) + bar(entity));
}
用法:

/* Initialize... */
fields_definition for_type1 = {0,4,8};
fields_definition for_type2 = {4,8,0};

configure(for_type2);

/* ... and use */
entity_type2 e;
some_operation(&e);
设置字段定义也可以通过类似于

entity_type2 t2;
fields_definition for_type2 = {
    &(t2.a)-&t2,
    &(t2.b)-&t2,
    &(t2.c)-&t2
};

(同样,已经有一段时间了,所以我不记得具体是怎么做的。)我相信有些编译器有一个内置函数,用于获取结构中的字段偏移量,这会更干净,但可移植性较差。

我会定义函数来获取所需的值,并向函数传递指针。您甚至可以传递一个包含所需函数指针的结构

struct Interface {
  unsigned char  (*manufacturer)(void);
  unsigned short (*top_speed)(void);
}
struct Interface CarInterface  = {&Car_manufacturer, &Car_top_speed};
struct Interface AutoInterface = {&Auto_manufacturer, &Auto_top_speed};

const char *car_manager__get_manufacturer_name(car_manager_t *self, Interface i)
{
  return self->manufacturers[(*i.manufacturer)()];
}
我已经很久没有写C了;如有必要,请更正我的语法