2

在以下情况下最好的解决方案是什么:

  • 我们的 API 返回一个结构给用户
  • 我们希望用户能够阅读其内容
  • 我们不希望用户更改它,因为它可能会传递给其他一些 API 函数并且它的内容应该是正确的?
4

6 回答 6

2

您的函数可以返回指向 const 结构的指针。然后:

  • 不允许调用者通过指向 const 结构的指针来修改结构。AC 实施应强制执行此规则。
  • 如果调用者将指向 const 结构的指针传递给 API 中的另一个函数,则 C 规则允许该函数将指向 const 结构的指针转换为指向非 const 结构的指针。如果结构没有定义为 const(例如,它被创建为非常量,但指向它的指针被转换为指向 const 结构的指针),则允许函数通过新转换的指针修改结构到非常量结构。
  • C 规则还允许调用者进行同样的转换和修改。显然,调用者不应该这样做,而您是在依靠他们的善意不这样做。因此,该技术可以防止通过返回的指针进行无意修改,但不能防止通过转换后的指针进行恶意修改。

更进一步,您可以只向调用者提供结构的不完整声明,仅显示其名称(如 中struct foo;)并且不定义其内容(如struct foo { int x;… };)。当调用者只有一个不完整的结构声明时,他们可以接收一个指向该结构的指针,并且可以将它存储并作为参数传递,但他们不能使用它来访问该结构(除非通过异常方式,例如转换它指向另一个类型的指针或通过提供自己的结构定义)。

如果调用者只有一个不完整的结构声明,但必须能够使用结构的内容,则必须提供额外的函数来接受指向结构的指针作为参数并从结构内部返回信息。

于 2013-08-13T11:39:53.030 回答
2

不是返回一个结构,而是返回一些可以让你恢复结构的东西(指向结构的指针应该可以工作,但你可以使用其他东西),而不是让用户访问它的字段,而是给他一组函数(或宏)用于访问这些领域。

我认为这称为不透明指针。

于 2013-08-13T10:00:52.590 回答
1

我认为每次使用调用此函数时,您都可以复制此结构并返回副本以使用。

这样,每次调用该函数时,都会创建一个新副本。

另外,你可以给用户malloc一个内存并给API地址,API只是memset用来填充地址,这样用户在使用完数据后可以释放内存。

opaque pointer 如果您不想将结构存储在任何地方,也可以使用 a 。

PS:我在我的命令中说出第三个建议,然后我得到了一个反对意见,而我看到其他人将这个添加到他的答案中并获得了一个赞成票,而且我们都没有先有这条线,这怎么会发生!

于 2013-08-13T09:54:04.523 回答
1

要扩展此处的答案,建议使用 opaque struct

在 C 中,很少有方法可以防止人们访问您的数据。如果您将structs公共 API 的参数和返回值作为参数和返回值进行传递,那么您可以通过一些方法隐藏数据或通过合同强制您的用户不访问所述数据

opaque 最明显的常见用法可能struct<stdio.h> FILE *. 每当您使用标准库读取/写入/查询文件时,您只需将您的文件传递struct FILE *给 libc I/O 函数之一,例如fwrite. 查看结构会导致未定义的行为,因为不能保证跨平台的实现相同。

如果您希望您的用户能够修改某些数据而不是其他数据,您可以执行以下操作:

typedef struct 
{
    void * _my_private_data; //KEEP OUT
    char * name;
    int count;
    //etc
}my_api_type;

然后,您可以定义向用户公开的所有函数调用的第一个参数,以采用其中一个参数structs

my_api_type set_internal_flag(my_api_type * obj, int flag);

确保您的私有数据保持隐藏状态后,您的实现可以保证无论您如何定义void *API 函数背后的结构,都可以在规范更改时保持兼容,并且用户在某些内容更新时不必修改他们的代码。

于 2013-08-13T10:45:11.580 回答
1

您无法阻止用户访问结构的内容。如果这是一个要求,您将必须返回一个不透明值并添加一个 API 来获取这些不透明值之一并从中返回各个值。

于 2013-08-13T10:25:20.473 回答
1

如果您不希望用户弄乱 struct 内部结构,您可以返回一个只能使用您定义的访问器函数读取的不透明指针。

于 2013-08-13T10:01:08.823 回答