【问题标题】:Interface like in c language?类似c语言的界面?
【发布时间】:2017-12-30 02:53:00
【问题描述】:

我想创建一个使用结构和围绕该结构的函数的程序,例如树。

界面类似于:

typedef struct _trie *Trie;

void foo1(Trie trie);
int foo2(Trie trie);
...

我想为此创建两个实现,它们将位于以下文件中:

  • first_trie.c、first_trie.h
  • second_trie.c、second_trie.h

使用界面的第三个文件:

  • use_trie.c

目标是编译 use_trie.c 两次,一次使用 second_trie.h,另一次使用 first_trie.h。

如何防止use_trie抱怨不知道Trie? 如何构建一个使用那些不同的标头构建两次 use_trie 的 makefile?

【问题讨论】:

  • 如果两个实现有相同的接口,你只需要一个.h文件。编译是通过文件完成的,所以你只需要担心链接。
  • 他会抱怨不知道 _trie 因为它在其他文件中
  • @Pixeuh:你需要设计界面让.h文件拥有主文件所需的一切。
  • 谨防使用以下划线开头的名称。 C11 §7.1.3 Reserved identifiers 说: • 所有以下划线和大写字母或另一个下划线开头的标识符始终保留以供任何使用。 — • 所有以下划线开头的标识符始终保留用于在普通名称空间和标记名称空间中用作具有文件范围的标识符。您正在使用struct _trie 踩在薄冰上。不过,你会和很多其他人在一起;人们经常滥用这些规则。
  • 顺便说一句,在类型中隐藏指针的品味很差。我更喜欢 typedef struct trie_st MyTrie; 然后 void foo1(MyTrie* trie); 因为你想在函数声明中显示指针参数。

标签: c makefile header-files


【解决方案1】:

您需要一个标头 trie.h,供以下人员使用:

  • first_trie.c — 因此它可以定义与其中定义的公共接口匹配的函数。
  • second_trie.c — 因此它可以定义与其中定义的公共接口匹配的函数。
  • use_trie.c — 因此它可以使用其中定义的公共接口声明的函数。

除非 trie 代码太大以至于需要跨多个源文件溢出,否则您不需要(或不想要)first_trie.hsecond_trie.htrie.h 中的单一通用定义完成了这项工作。实际 trie 结构的内部细节完全保存在实现每个 trie 的源文件中。

如 cmets 中所述:

  • 以下划线和大写字母或另一个下划线开头的所有标识符始终保留用于任何用途。
  • 以下划线开头的所有标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。

您使用struct _trie 正在如履薄冰。不过,你会和很多其他人在一起;人们经常滥用这些规则。

  • 谨慎使用typedef 作为指针。有关详细讨论,请参阅Is it a good idea to typedef pointers

    请注意,您通常应将 FILE 视为不透明类型,但您始终声明 FILE *fp 等。

makefile 应该没什么问题。一个简单的大纲可以很简单:

TRIE1.c = first_trie.c
TRIE2.c = second_trie.c
PROG.c  = use_trie.c
TRIE1.o = ${TRIE1.c:.c=.o}
TRIE2.o = ${TRIE2.c:.c=.o}
PROG.o  = ${PROG.c:.c=.o}

PROG1 = use_trie1
PROG2 = use_trie2

all: ${PROG1} ${PROG2}

${PROG1}: ${PROG.o} ${TRIE1.o}
    ${CC} -o $@ ${CFLAGS} ${PROG.o} ${TRIE1.o} ${LDFLAGS} ${LDLIBS}

${PROG2}: ${PROG.o} ${TRIE2.o}
    ${CC} -o $@ ${CFLAGS} ${PROG.o} ${TRIE2.o} ${LDFLAGS} ${LDLIBS}

您可能想要添加规则,告诉 Make 标题也很重要:

TRIE.h = trie.h

${TRIE1.o}: trie.h
${TRIE2.o}: trie.h
${PROG.o}:  trie.h

您不一定需要将源文件添加到依赖项列表中;这样做是完整的,但不是必须的。

请注意,将first_trie.osecond_trie.o 放在一个库中是个坏主意。这两个目标文件中的哪一个与任何给定程序链接是不确定的。它甚至不需要是一致链接的同一个文件(尽管它可能是)。您将需要单独的库 - 或将目标文件与您要使用的链接明确分开。

【讨论】:

    【解决方案2】:

    如果use_foo.c 只使用公共接口中接受指针的函数(并且它永远不需要取消引用其中一个指针),则它不需要了解内部结构。类型声明就足够了。这称为opaque pointer

    【讨论】:

      猜你喜欢
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多