首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C程序设计

C程序设计
EN

Stack Overflow用户
提问于 2013-10-10 09:13:56
回答 3查看 258关注 0票数 8

对于健壮的C程序来说,这样做好/正确吗?

代码语言:javascript
复制
//File1 => Module1.h

static int Fun(int);

struct{
int (*pFn)(int)
}Interface;

//File2 2 =>模块1.c

代码语言:javascript
复制
static int Fun(int){
//do something
}

Interface* Init(void)
{
  Interface *pInterface = malloc(sizeof(Interface));
  pInterface->pFn = Fun;
  return pInterface;
}

//File 3 => Module2.c
#include"Module1.h"
main()
{
  Interface *pInterface1 = Init();
  pInterface1->pFn(5);
}

我的目的是让每个模块暴露一个接口..。

问题:

  1. 写一个像上面这样的C代码来公开一个接口好吗..。??
  2. 有什么更好的方法可以公开界面??
  3. 对于C程序设计原则(不是C++)有参考吗?
EN

回答 3

Stack Overflow用户

发布于 2013-10-11 05:34:18

对于动态加载的模块来说,这更符合惯例。(或者其他类似的东西。)

通常,两个源文件之间的接口是使用直接访问的extern函数和对象定义的。你需要为做任何更复杂的事情找个理由。

票数 1
EN

Stack Overflow用户

发布于 2013-10-11 05:53:38

  1. 如果您使用它来解决简单的任务,它可能只会增加代码基础和复杂性。但某些地方可能有用。 例如:如果您想在C中实现战略模式,这是一种方法。
  2. 可以使用Interface对用户隐藏一级ADT模式结构的内容。或者你可以结合上面的模式。
票数 0
EN

Stack Overflow用户

发布于 2013-10-11 06:02:42

我的简短回答是不。

忽略那些指出不应该在.h文件中声明静态函数的注释(这是您想要隐藏的部分--毕竟它是静态的),这里有一些需要记住的事情。

似乎您正在尝试使用该接口,以便将实现从模块的使用者中分离出来;这是一个崇高的目标。这可以允许增加灵活性,因为实现可以在不中断调用代码的情况下更改.c文件。但是,考虑一下您定义的接口。

使用该模块的任何代码都应该能够通过Init获得接口实例(尽管这需要包含在.h文件中)。该接口实例将指向要使用的函数。其中一个函数具有签名。

代码语言:javascript
复制
int Fun(int);

那你藏了什么?当然,您可以更改他们正在调用的函数,但是您仍然必须提供一个带有该签名的函数。

或者,您只需将.h定义为:

代码语言:javascript
复制
int Fun(int);

然后在.c文件中,如下所示:

代码语言:javascript
复制
static int StaticFun(int i)
{
    // something
}

int Fun(int i)
{
    StaticFun(i);
}

您可以根据它管理的内部状态或配置文件进行有趣的调用,不管您想要什么。为什么这样更好?除了简单之外,它还是一个静态调用;例如,编译器可以内联对StaticFun的调用,甚至是函数StaticFun。通过函数指针进行调用通常会对性能造成明显的影响。

现在,可能存在"Interface“对象的情况,如您所定义的那样。但我倾向于建议,在你的情况下没有一个,不是未经修改。

假设您的Init函数更改为:

代码语言:javascript
复制
Interface* Init(some state info);

现在,您返回的Interface对象可以根据传入的状态或配置进行更改,这允许模块动态映射函数。基本上,我的观点是,如果您实际上是在调用下面的静态函数,那么您的工作比需要的要努力得多,并阻止编译器优化。

请注意,如果您要走接口路线(我现在正在做一个类似的项目),那么我可以建议修改吗?就像..。

.h文件:

代码语言:javascript
复制
const Interface* Init(some state);

.c文件:

代码语言:javascript
复制
static int FunTyp1(int);
static int FunTyp2(int);


static const Interface typ1 = { &FunTyp1 };
static const Interface typ2 = { &FunTyp2 };

const Interface* Init(some state)
{
    if (some state == type1)
       return &typ1;
    else if (some state == type2)
       return &typ2;
}

优势:

  1. 您可能不希望使用代码来修改接口?至少我想不出一个好的理由。
  2. 静态地定义它可以避免不必要的堆分配和内存泄漏,当使用者反复请求Interface对象时,忘记释放它们(或者不知道应该释放它们-谁拥有这个对象?)
  3. 您可以为流程中的所有消费代码共享Interface对象的单个(静态)实例,而不必担心有人会更改它。

注意,通过具有多个静态初始化实例,您可以为要支持的每个函数映射定义一个不同的"Interface“对象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19291647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档