我想隐藏struct定义,所以我在源文件中定义struct,如下所示:
//a.c
#include "a.h"
struct a_s
{
int a;
int b;
};
int func(a_t *a)
{
printf("%d\n", a->a);
return 0;
}我在头文件中声明了该结构,如下所示:
//a.h
#ifndef TEST
#define TEST
#include <stdio.h>
#include <stddef.h>
typedef struct a_s a_t;
#endif然后我使用结构a_t int main.c文件,如下所示:
#include "stddef.h"
#include "a.h"
int main()
{
a_t a;
a.a =2;
func(&a);
return 0;
}但是当我用gcc -c main.c编译main.c时,它失败了,因为
main.c: In function ‘main’:
main.c:7:15: error: storage size of ‘a’ isn’t known
struct a_s a;为什么这是失败的?
发布于 2019-12-04 10:28:41
如果您实例化一个对象A a,链接器将搜索A的定义,以便编译器知道它需要分配多少内存。它搜索a.h,并找到一个类型定义,但没有声明,所以错误是说它不知道A的大小。
如果程序的目的是对用户隐藏声明(和定义),你将需要使用A *a,因为这告诉编译器“有一个类型A,它的内存将从这个内存位置开始存储”,因此在内存应该动态分配和释放的运行时之前,不需要任何关于数据大小或布局的信息。
这种方法允许开发人员向用户公开接口,而用户不需要知道数据结构的任何细节,并允许软件更新和数据结构修改,同时保持面向外的头文件相同(并保持测试通过)。
发布于 2019-12-04 10:49:55
如果要隐藏结构定义,则用户只能定义类型的指针,而您必须实现创建结构实例的api (通过malloc)和释放结构实例的api (通过free)
发布于 2019-12-04 12:59:10
您不能创建尚未定义的结构的实例,因为编译器不知道要为它分配多少空间。
您不能访问尚未定义的struct的成员,因为编译器不知道它们的类型。
但是,您可以使用指向尚未定义的结构的指针。这使得人们可以做如下事情:
foo.h
typedef struct Foo Foo
Foo* Foo_new(int a, int b);
void Foo_destroy(Foo* this);
void Foo_set_a(Foo* this, int a);
void Foo_set_b(Foo* this, int b);
int Foo_get_a(Foo* this);
int Foo_get_b(Foo* this);
// ...foo.c
#include "a.h"
struct Foo {
int a;
int b;
};
Foo* Foo_new(int a, int b) {
Foo* this = malloc(sizeof(Foo));
this->a = a;
this->b = b;
return this;
}
void Foo_destroy(Foo* this) { free(this); }
void Foo_set_a(Foo* this, int a) { this->a = a; }
void Foo_set_b(Foo* this, int b) { this->b = b; }
int Foo_get_a(Foo* this) { return this->a; }
int Foo_get_b(Foo* this) { return this->b; }
// ...main.c
#include <stdio.h>
#include "foo.h"
int main(void) {
Foo* foo = Foo_new(3, 4);
Foo_set_a(foo, 5);
printf("%d %d\n",
Foo_get_a(foo),
Foo_get_b(foo),
);
Foo_destroy(foo);
return 0;
}如果你想要一个真正不透明的类型,你甚至可以把指针包含在type中。通常,这是一种糟糕的做法,但在这种特殊情况下,它在一定程度上是有意义的。有关此概念的更多信息,请参阅this。
https://stackoverflow.com/questions/59167934
复制相似问题