c - 函数参数类型兼容性

标签 c c99 c89 function-call function-parameter

我隐藏了 struct 类型中的一些结构字段,以使公共(public) API header 更加清晰。

首先,我使用这种样式来隐藏(实际上不是隐藏,只是与公共(public)可编辑成员分开)一些成员,

include/scene.h

typedef struct ScenePrivateFields {
  SceneFlags flags;
  /* other members */
} ScenePrivateFields;

typedef struct Scene {
  ScenePrivateFields _priv;
  RootNode           rootNode;
  /* other members */
} Scene;

对于这种风格,我总是在函数参数中使用场景类型,然后使用 _priv 成员访问私有(private)字段。但是将所有私有(private)字段保留在公共(public) header 中会使 header 变得更加复杂

最后我换了另一种风格

include/scene.h

typedef struct Scene {
  RootNode rootNode;
  /* other members */
} Scene;

EXPORT
Scene*
allocScene(void);

src/types/impl_scene.h

typedef struct SceneImpl {
  Scene      pub;
  SceneFlags flags;
  /* other members */
} SceneImpl;

例如,如果我有这样的函数:

include/scene.h

void
renderScene(Scene * __restrict scene, /* other params */);

我必须将场景转换为 SceneImpl 才能访问私有(private)字段。我这样做是这样的:

src/scene/scene.c

void
renderScene(Scene * __restrict scene, /* other params */) {
  SceneImpl *sceneImpl;

  sceneImpl = (SceneImpl *)scene;
}

为了避免强制转换每个函数调用,我想也许我可以做这样的事情,如果它是合法的并且不违反 C 标准:

src/scene/scene.c

void
renderScene(SceneImpl * __restrict sceneImpl, /* other params */) {
  /* skip casting scene to sceneImpl */
}

由于SceneSceneImpl的第一个成员,我可以用Scene定义公共(public)api(函数)并用SceneImpl定义实现(函数)吗?我认为它会起作用,因为两者都是指针,这是有效的还是好主意?

注意:我使用 -fstrict-aliasing 进行编译

编辑:FWIW,这里是分配函数实现,用户必须使用此函数来分配结构:

EXPORT
Scene*
allocScene(void) {
  SceneImpl *sceneImpl;

  sceneImpl = calloc(1, sizeof(*sceneImpl));

  /* initialize pulic part */
  sceneImpl->pub.field1 = ...

    /* initialize private part */
  sceneImpl->priv_field1 = ...

  /* return public part */
  return &sceneImpl->pub;
}

最佳答案

您可以使用不透明类型作为数据的私有(private)部分。

在公共(public) header 中,定义结构如下:

// forward declaration of struct ScenePrivateFields 
typedef struct ScenePrivateFields ScenePrivateFields;

typedef struct Scene {
  ScenePrivateFields *_priv;    // now a pointer
  RootNode           rootNode;
  /* other members */
} Scene;

然后在您的实现文件中,定义私有(private)结构:

struct ScenePrivateFields {
  SceneFlags flags;
  /* other members */
}

您还需要定义一个函数,该函数动态创建 struct ScenePrivateFields 的实例并返回指向它的指针以填充公共(public)结构中的指针。

关于c - 函数参数类型兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47518485/

相关文章:

c - 在负偏移量处分配带有变量的记录

C 和 OpenMP : nowait for loop in a do loop

c - 使用多线程时低于预期的加速

c - 枚举对象设置为不等于其各自枚举常量的值

c - stdint.h 中定义的 C99 有符号整数类型是否在溢出时表现出明确定义的行为?

c - 缺少一些简单的东西,C 程序不会接受答案?

c - Visual Studio 将不完整数组视为零长度数组

c - 没有标签的 switch 语句代码

c - floor() 是否返回可以完全表示的东西?

iphone - ansi c应用程序的二进制文件可以在iPhone上运行吗?