如何在通用标头中类型定义实现定义的结构?

尼克尼爵士

我有一个C项目,旨在将其移植到各种(PC和嵌入式)平台上。

应用程序代码将使用各种调用,这些调用将具有特定于平台的实现,但共享一个通用的(通用)API以帮助实现可移植性。我试图确定最合适的方法来声明函数原型和结构。

到目前为止,这是我想出的:

main.c:

#include "generic.h"

int main (int argc, char *argv[]) {
    int  ret;
    gen_t  *data;

    ret = foo(data);
    ...
}

generic.h :(与平台无关的包含)

typedef struct impl_t gen_t;

int foo (gen_t *data);

impl.h :(特定于平台的声明)

#include "generic.h"

typedef struct impl_t {
    /* ... */
} gen_t;

impl.c :(特定于平台的实现)

int foo (gen_t *data) {
    ...
}

建造:

gcc -c -fPIC -o platform.o impl.c
gcc -o app  main.c platform.o

现在,这似乎可以正常工作……因为它可以编译。但是,我通常不标记结构,因为它们从未在typedef'd别名之外访问这是一个小巧的选择,但是我想知道是否有一种方法可以用匿名结构实现相同的效果?

我也要求后代,因为我搜索了一段时间,发现的最接近的答案是:(Link

在我的情况下,这不是正确的方法,因为应用程序明确地不应直接包含实现标头-关键是要使程序与平台脱钩。

我看到了其他几种不太理想的方法来解决此问题,例如:

generic.h:

#ifdef PLATFORM_X
#include "platform_x/impl.h"
#endif

/* or */

int foo (struct impl_t *data);

这些似乎都没有特别吸引人,而且绝对不是我的风格。尽管我不想游刃有余,但是当可能有更好的方法来实现我所想的时,我也不希望样式冲突。所以我认为typedef解决方案是在正确的轨道上,而这只是我剩下的struct标签。

有什么想法吗?

乔纳森·莱夫勒

您当前的技术是正确的。尝试使用匿名(未标记)功能将struct失败,您将不得不做的事情–您必须公开struct到处定义的详细信息,这意味着您不再拥有不透明的数据类型。


在一条评论中user3629249说:

头文件包含的顺序意味着文件有对结构的前向引用generic.h也就是说,在定义结构之前,先使用它。这不太可能编译。

对于问题中显示的标题,这种观察是不正确的。它对于示例main()代码是准确的(直到添加此响应之前我才注意到)。

关键是显示的接口函数采用或返回类型的指针,而类型gen_t又映射到struct impl_t指针。只要客户代码不需要为该结构分配空间,也不需要取消对结构的指针的引用来访问该结构的成员,则客户代码不需要知道该结构的细节。将结构类型声明为存在就足够了。您可以使用其中任何一个来声明存在struct impl_t

struct impl_t;

typedef struct impl_t gen_t;

后者还引入gen_t了类型的别名struct impl_t另请参见C标准的哪一部分可以编译此代码?C标准是否认为struct uperms此标头中存在一种或两种条目类型?

问题中的原始main()程序是:

int main (int argc, char *argv[]) {
    int  ret;
    gen_t  data;

    ret = foo(&data);
    …
}

此代码不能以gen_t不透明(非指针)类型进行编译可以正常工作:

typedef struct impl_t *gen_t;

它不能与以下内容一起编译:

typedef struct impl_t gen_t;

因为编译器必须知道为分配正确的空间的结构的data大小,但是编译器无法通过定义不透明类型来知道该大小。(请参阅typedef指针的一个好主意吗?有关对结构的指针的类型定义。)

因此,main()代码应类似于:

#include "generic.h"

int main(int argc, char **argv)
{
    gen_t *data = bar(argc, argv);
    int ret = foo(data);
    ...
}

其中(对于本示例)bar()被定义为extern gen_t *bar(int argc, char **argv);,因此它返回一个指向不透明类型的指针gen_t

对于始终使用名称struct tagname还是使用a更好typedefLinux内核是不使用该typedef机制的大量代码体所有结构都是明确的struct tagname另一方面,C ++消除了对显式的需求typedef写作:

struct impl_t;

在C ++程序中,意味着名称impl_t现在是类型的名称。由于不透明的结构类型需要一个标记(否则最终会用到void *所有东西,这在很多方面都是不好的,但是主要原因是使用会失去所有类型的安全性void *;请记住,typedef为基础类型引入别名,而不是一种新的独特类型),我用C编写的代码模拟C ++:

typedef struct Generic Generic;

我避免_t在我的类型上使用后缀,因为POSIX保留了_t供实现使用*的实现(另请参见类型后跟_t代表什么?)。您可能很幸运,可以摆脱它。我已经在代码库上工作过,其中的类型类似于dec_tloc_t由代码库定义(它不是实现的一部分,其中“实现”是指C编译器及其支持的代码,或C库及其支持的代码),这两种类型都造成了数十年的痛苦,因为移植代码的某些系统定义了这些类型,这也是系统的特权。我设法摆脱的名字之一;其他我没有。'真痛苦!如果必须使用_t(这是指示某种类型的一种简便方法),我建议也使用一个独特的前缀:例如,对于pqr_typename_t某些项目pqr

*请参阅POSIX标准“名称空间”第二个表的底行

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在xml文件的标头中定义json的类型

来自分类Dev

定义在C标头中传递结构的函数

来自分类Dev

Python3:如何在方法标头中定义异常?

来自分类Dev

标头中的typedef的限制,源中定义的结构

来自分类Dev

在C的标头中定义别名类型的extern变量

来自分类Dev

如何在标头中添加自定义标签以使WordPress中的字体变大?

来自分类Dev

HTTP :: Daemon:如何在HTTP标头中为服务器设置自定义值?

来自分类Dev

构建自定义linux内核时,如何从标头中剥离未使用的体系结构,驱动程序等?

来自分类Dev

如何在Scala中定义通用异常类型?

来自分类Dev

查询实现通用接口的类的通用类型定义

来自分类Dev

如何在nodejs中的Swagger UI(swagger.json)中的标头中表示自定义令牌

来自分类Dev

使用在另一个标头中定义的结构

来自分类Dev

标头中的静态函数定义

来自分类Dev

标头中的静态函数定义

来自分类Dev

如何在没有类型定义的情况下定义通用类型的“具有属性”约束?

来自分类Dev

在php标头中使用自定义定义的变量

来自分类Dev

仅标头库:使用稍后在标头中定义的类

来自分类Dev

如何定义方法返回的结构类型

来自分类Dev

如何在golang类型结构中将列类型定义为长文本?

来自分类Dev

如何在C ++类中实现在C标头中用“ extern”子句指定的函数?

来自分类Dev

定义在主程序标头上定义的堆栈结构数组的数据类型

来自分类Dev

如何在自定义数据结构中实现begin()成员函数?

来自分类Dev

定义OCaml类型结构

来自分类Dev

如何在Jackson中为通用类型创建自定义解串器?

来自分类Dev

如何在通用类型的gson上使用自定义反序列化?

来自分类Dev

如何将自定义HTML放入Yii2 GridView标头中?

来自分类Dev

C ++如何解决标头中未定义的名称空间?

来自分类Dev

如何使用ffmpeg将自定义数据保存到电影文件的标头中?

来自分类Dev

Google Cloud Load Balancer 自定义标头中的 unicode 值如何编码?

Related 相关文章

  1. 1

    如何在xml文件的标头中定义json的类型

  2. 2

    定义在C标头中传递结构的函数

  3. 3

    Python3:如何在方法标头中定义异常?

  4. 4

    标头中的typedef的限制,源中定义的结构

  5. 5

    在C的标头中定义别名类型的extern变量

  6. 6

    如何在标头中添加自定义标签以使WordPress中的字体变大?

  7. 7

    HTTP :: Daemon:如何在HTTP标头中为服务器设置自定义值?

  8. 8

    构建自定义linux内核时,如何从标头中剥离未使用的体系结构,驱动程序等?

  9. 9

    如何在Scala中定义通用异常类型?

  10. 10

    查询实现通用接口的类的通用类型定义

  11. 11

    如何在nodejs中的Swagger UI(swagger.json)中的标头中表示自定义令牌

  12. 12

    使用在另一个标头中定义的结构

  13. 13

    标头中的静态函数定义

  14. 14

    标头中的静态函数定义

  15. 15

    如何在没有类型定义的情况下定义通用类型的“具有属性”约束?

  16. 16

    在php标头中使用自定义定义的变量

  17. 17

    仅标头库:使用稍后在标头中定义的类

  18. 18

    如何定义方法返回的结构类型

  19. 19

    如何在golang类型结构中将列类型定义为长文本?

  20. 20

    如何在C ++类中实现在C标头中用“ extern”子句指定的函数?

  21. 21

    定义在主程序标头上定义的堆栈结构数组的数据类型

  22. 22

    如何在自定义数据结构中实现begin()成员函数?

  23. 23

    定义OCaml类型结构

  24. 24

    如何在Jackson中为通用类型创建自定义解串器?

  25. 25

    如何在通用类型的gson上使用自定义反序列化?

  26. 26

    如何将自定义HTML放入Yii2 GridView标头中?

  27. 27

    C ++如何解决标头中未定义的名称空间?

  28. 28

    如何使用ffmpeg将自定义数据保存到电影文件的标头中?

  29. 29

    Google Cloud Load Balancer 自定义标头中的 unicode 值如何编码?

热门标签

归档