我正在考虑在C语言中实现一个简单的界面模式。
一个关键特征是它将为接口的公共头提供的不透明结构提供多个定义,也就是说,不同的实现将为该结构提供不同的下层数据(因此跨越不同的转换单元,相同结构将有不同的实现。)
我无法找到任何关于这是好的还是坏的设计模式的参考。至少它似乎没有违反严格的别名规则,只依赖于共同的第一个元素的一致顺序和填充,这是由C标准保证的(据我所知)。当然我知道C中的面向对象模式,但我看不到这个特定的模式。
这可以接受吗?甚至使用过这种模式吗? (我找不到任何东西)
为了便于理解,以下是三个源文件的工作示例:
reader.h(公共接口定义)
#ifndef READER_H
#define READER_H
typedef struct reader_s reader_t;
char reader_read(reader_t* r);
#endif
reader.c(界面的胶水逻辑)
#include "reader.h"
typedef char (reader_f)(reader_t*);
struct reader_s{
reader_f* rfunc;
};
char reader_read(reader_t* r)
{
return r->rfunc(r);
}
reader1.h(接口的实现,标题)
#ifndef READER1_H
#define READER1_H
#include "reader.h"
reader_t* reader1_get(void);
#endif
reader1.c(接口的实现,代码)
#include "reader1.h"
typedef char (reader_f)(reader_t*);
struct reader_s{
reader_f* rfunc;
int pos;
};
static char reader1_read(reader_t* r);
reader_t reader1_obj = {&reader1_read, 0};
reader_t* reader1_get(void)
{
return &reader1_obj;
}
static char reader1_read(reader_t* r)
{
char rval = 'A' + (r->pos);
(r->pos) = (r->pos) + 1;
if ((r->pos) == 24){ (r->pos) = 0; }
return rval;
}
main.c(示例用法)
#include "reader1.h"
#include <stdio.h>
int main(void)
{
reader_t* rd = reader1_get();
int i;
printf("\n");
for (i = 0; i < 60; i++){
printf("%c", reader_read(rd));
}
printf("\n");
return 0;
}
可能接口应该为实现者提供另一个头文件,提供包含函数指针的结构头的定义。也许它甚至可以指向一个类结构,其中包含那些用于最小化具有许多方法的类的对象大小的类结构。
答案 0 :(得分:1)
在这种情况下,C标准中的任何内容都不会定义行为,但如果实现指定了数据类型的存储格式以及处理模块间调用的方式,则可以定义行为。但请注意,某些实现具有&#34;链接时优化&#34;可能并不总是在&#34; normal&#34;中执行模块间调用。记录时尚。
我唯一能看到这种方法可行的方法是,如果与某个类型相关联的公共API希望允许代码直接声明该类型的实例,或者使用赋值运算符,但是否则不需要承诺为任何其他目的公开字段布局。在这种情况下,拥有包含uint32[]
或uint64[]
之类的公共结构类型可能是一种合理的方法,即使所有处理该类型内部的代码都使用了&#34; real&#34 ;结构类型。如果内部结构类型发生变化,只要大小保持不变,这样的设计将避免重新编译客户端代码的需要。另一方面,我不会考虑任何这样的设计代码,可能需要使用基于gcc样式的基于类型的别名来处理#34;优化&#34;启用后,由于gcc故意对这些优化会破坏代码的地方视而不见。