如何在C中隐藏结构的声明?

10 c

在问题中我们为什么要在C中经常输入一个结构?,放松回答:

在后一种情况下,您不能返回Point by值,因为它的声明对头文件的用户是隐藏的.例如,这是GTK +中广泛使用的技术.

如何完成声明隐藏?为什么我不能按值返回Point?

加:

我理解为什么我不能通过值返回结构,但是,仍然很难理解为什么我不能在我的函数中尊重这一点.即如果我的结构有名为y的成员,为什么我不能这样做?

 pointer_to_struct->y = some_value; 
Run Code Online (Sandbox Code Playgroud)

我为什么要使用方法呢?(像Gtk +)

谢谢你们,再次为我糟糕的英语道歉.

Tim*_*mbo 30

使用公共头文件,私有头文件和实现文件来查看这个库的示例.

在文件public.h中:

struct Point;

Point* getSomePoint();
Run Code Online (Sandbox Code Playgroud)

在文件private.h中:

struct Point
{
    int x;
    int y;
}
Run Code Online (Sandbox Code Playgroud)

在文件private.c中:

Point* getSomePoint()
{
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

如果将这三个文件合并到一个库中,则只将public.h和库对象文件提供给库的使用者.

getSomePoint必须返回一个指针Point,因为public.h没有定义大小Point,只有它是一个结构并且它存在.库的消费者可以使用指针Point,但无法访问成员或复制它们,因为他们不知道结构的大小.

关于你的进一步问题:你不能解除引用,因为使用库的程序只有来自private.h的信息,它不包含成员声明.因此它无法访问点结构的成员.

您可以将此视为C的封装功能,就像您将C++类的数据成员声明为私有一样.


Joh*_*itb 5

他的意思是你不能在头文件中返回struct by-value,因为为此,必须完全声明struct.但这种情况发生在C文件中(X在他的示例中,使完整类型的声明在C文件中"隐藏",而不是暴露在标题中).如果这是结构的第一个声明,则下面仅声明一个不完整的类型

struct X;
Run Code Online (Sandbox Code Playgroud)

然后,您可以声明该功能

struct X f(void);
Run Code Online (Sandbox Code Playgroud)

但是你不能定义函数,因为你不能创建那种类型的变量,更不用说返回它(它的大小是未知的).

struct X f(void) { // <- error here
  // ...
}
Run Code Online (Sandbox Code Playgroud)

发生错误是因为"x"仍然不完整.现在,如果只包含带有不完整声明的标题,那么就不能调用该函数,因为函数调用的表达式会产生一个不完整的类型,这是禁止发生的.

如果您要struct X在两者之间提供完整类型的声明,那么它将是有效的

struct X;
struct X f(void);

// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
  // ...
}
Run Code Online (Sandbox Code Playgroud)

这也适用于使用方式typedef:它们都命名相同,(可能不完整)类型.一次使用普通标识符X,另一次使用标记struct X.


小智 5

在头文件中:

typedef struct _point * Point;
Run Code Online (Sandbox Code Playgroud)

在编译器看到它后,它知道:

  • 有一个名为_point的结构
  • 有一个指针类型Point可以引用_point

编译器不知道:

  • _point结构是什么样的
  • 它包含哪些成员
  • 它有多大

并且编译器不仅不知道它 - 我们程序员也不知道它.这意味着我们无法编写依赖于_point属性的代码,这意味着我们的代码可能更具可移植性.

鉴于上面的代码,您可以编写如下函数:

Point f() {
   ....
}
Run Code Online (Sandbox Code Playgroud)

因为Point是一个指针,指针的大小都相同,编译器不需要知道任何其他内容.但是你不能编写一个按值返回的函数:

_point f() {
  ....
}
Run Code Online (Sandbox Code Playgroud)

因为编译器对_point没有任何了解,特别是它的大小,它是构造返回值所需要的.

因此,我们只能通过Point类型引用_point,它实际上是一个指针.这就是为什么标准C具有类似FILE的类型,它只能通过指针访问 - 您无法在代码中创建FILE结构实例.


Joh*_*ohn 5

老问题,更好的答案:

在头文件中:

typedef struct _Point Point;
Run Code Online (Sandbox Code Playgroud)

在 C 文件中:

struct _Point
{
   int X;
   int Y;
};
Run Code Online (Sandbox Code Playgroud)