在后一种情况下,您无法通过值返回Point,因为其声明对头文件的用户是隐藏的。例如,这是GTK+广泛使用的一种技术。
如何隐藏声明?为什么我不能按值返回Point?
补充:
我明白为什么不能按值返回结构体了,但是,为什么我不能在我的函数中解引用这个指针呢?例如,如果我的结构体有一个名为y的成员,我为什么不能这样做?
pointer_to_struct->y = some_value;
我为什么要使用方法来完成它?(例如Gtk +)
谢谢大家,再次抱歉我的英语不好。
在后一种情况下,您无法通过值返回Point,因为其声明对头文件的用户是隐藏的。例如,这是GTK+广泛使用的一种技术。
如何隐藏声明?为什么我不能按值返回Point?
补充:
我明白为什么不能按值返回结构体了,但是,为什么我不能在我的函数中解引用这个指针呢?例如,如果我的结构体有一个名为y的成员,我为什么不能这样做?
pointer_to_struct->y = some_value;
我为什么要使用方法来完成它?(例如Gtk +)
谢谢大家,再次抱歉我的英语不好。
请参考这个库的示例,其中使用了公共头文件、私有头文件和实现文件。
在文件public.h中:
struct Point;
struct Point* getSomePoint();
在private.h文件中:
struct Point
{
int x;
int y;
}
在 private.c 文件中:
struct Point* getSomePoint()
{
/* ... */
}
如果你将这三个文件编译成库,你只需要提供public.h和库对象文件给库的使用者。
getSomePoint
必须要返回一个指向Point
的指针,因为public.h没有定义Point
结构体的大小,只定义了它是个结构体并且存在。库的使用者可以使用Point
的指针,但是不能访问其成员或者复制它,因为他们不知道结构体的大小。
关于你进一步提出的问题: 你不能解引用它,因为使用库的程序只有private.h中的信息,其中没有成员声明。因此,它无法访问点结构的成员。
你可以将这看作是C语言的封装特性,就像你会将C++类的数据成员声明为私有一样。
struct X;
struct X f(void);
但是你无法定义该函数,因为你无法创建该类型的变量,更不用说返回它了(它的大小未知)。
struct X f(void) { // <- error here
// ...
}
struct X
,那么它就是有效的。struct X;
struct X f(void);
// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
// ...
}
typedef
的方式:它们都命名了相同的(可能是不完整的)类型。一次使用普通标识符X
,另一次使用标签struct X
。typedef struct _point * Point;
编译器看到这个代码后,它知道:
_point
的结构体。Point
可以引用struct _point
。编译器不知道:
struct _point
的具体内容是什么。struct _point
包含哪些成员。struct _point
的大小。不仅编译器不知道,我们作为程序员也不知道。这意味着我们不能编写依赖于struct _point
这些属性的代码,这样我们的代码就更具可移植性。
根据上述代码,您可以编写如下函数:
Point f() {
....
}
因为Point
是一个指针,而struct
指针的大小都相同,编译器不需要了解它们的其他信息。但是你不能编写一个返回值的函数:
struct _point f() {
....
}
struct _point
一无所知,尤其是它的大小,在构造返回值时需要这些信息。Point
引用 struct _point
。这也是标准C语言有像 FILE
这样只能通过指针访问的类型的原因 - 你不能在代码中创建一个 FILE
结构实例。旧问题,更好的答案:
在头文件中:
typedef struct _Point Point;
struct _Point
{
int X;
int Y;
};
typedef struct _Point Point;
Point * point_new(int x, int y);
Point
的实现细节,那么请参考以下内容。作为使用非透明指针的替代方案(如其他人所提到的),如果你想避免使用堆内存,你可以返回一个不透明的字节包:
// In public.h:
struct Point
{
uint8_t data[SIZEOF_POINT]; // make sure this size is correct!
};
void MakePoint(struct Point *p);
// In private.h:
struct Point
{
int x, y, z;
};
void MakePoint(struct Point *p);
// In private.c:
void MakePoint(struct Point *p)
{
p->x = 1;
p->y = 2;
p->z = 3;
}
pthreads
库中使用的各种结构体对于像pthread_t
、pthread_cond_t
等类型都使用不透明字节的结构体——您仍然可以在堆栈上创建这些结构体的实例(通常是这样做),但是您不知道其中的内容。只需查看您的/usr/include/pthreads.h
和它包含的各个文件即可了解更多信息。
file.c
中声明一个仅在file.c
中使用的结构体,这是否可行? - mercury0114file.c
文件中声明一个结构体,那么它只能在该声明点以下的file.c
文件内可见。 - Timbo