C 在头文件中声明结构
我在我的fifo.c文件中有类型C 在头文件中声明结构,c,declaration,C,Declaration,我在我的fifo.c文件中有类型fifo\u t定义,如下所示。在头文件中,这种类型的声明应该是什么?我想使此结构的内容仅在文件fifo.c中已知。此外,我不想通过struct struct\u name var创建此结构的实例。唯一有效的方法应该是fifo\t var typedef struct { uint8_t *buffer, uint8_t indexRead, uint8_t indexWrite, uint8_t used, uint8_t
fifo\u t
定义,如下所示。在头文件中,这种类型的声明应该是什么?我想使此结构的内容仅在文件fifo.c中已知。此外,我不想通过struct struct\u name var创建此结构的实例代码>。唯一有效的方法应该是fifo\t var代码>
typedef struct {
uint8_t *buffer,
uint8_t indexRead,
uint8_t indexWrite,
uint8_t used,
uint8_t size
} fifo_t;
如果希望能够像fifo\u t var一样在堆栈上创建它,则不能隐藏fifo\u t
的内容代码>因为大小(fifo\t)
未知
您可以在标题中对fifo\t
执行forvard声明:struct fifo\t代码>。在其他文件中,您将能够创建指向fifo\u t
的poiner,并使用应该在fifo.c中实现的函数来处理它们
fifo_t *var;
create(&var);
do_work(var);
destroy(var);
如果希望能够像fifo\u t var一样在堆栈上创建它,则不能隐藏fifo\u t
的内容代码>因为大小(fifo\t)
未知
您可以在标题中对fifo\t
执行forvard声明:struct fifo\t代码>。在其他文件中,您将能够创建指向fifo\u t
的poiner,并使用应该在fifo.c中实现的函数来处理它们
fifo_t *var;
create(&var);
do_work(var);
destroy(var);
如果您只想传递指向fifo\t
的指针,那么您只能在头文件中转发声明它。但是,未命名结构的typedef
仅在定义结构的内容时有效。因此,如果您不想要struct fifo\t var代码>要编译,您必须使用一些违反直觉的名称,例如fifo\u t\u
。例如:
typedef struct fifo_t_ fifo_t;
void fifo_use(fifo_t*); // ok, just uses pointer
然后在.c
文件中,执行(请注意,使用逗号分隔成员是无效的语法):
另外,请注意fifo\t var代码>不起作用,因为您需要知道结构的大小才能为其分配空间。您可以做的是,以对用户透明的方式在内部使用指针:
// in .h file:
typedef struct fifo_t_* fifo_t;
void fifo_init(fifo_t*);
void fifo_free(fifo_t);
void fifo_use(fifo_t);
// in .c file:
struct fifo_t_{
uint8_t *buffer;
uint8_t indexRead;
uint8_t indexWrite;
uint8_t used;
uint8_t size;
};
void fifo_init(fifo_t* f) {
*f = (fifo_t)malloc(sizeof(struct fifo_t_));
}
void fifo_free(fifo_t f) {
free(f);
}
void fifo_use(fifo_t f) {
f->indexRead = 1;
}
// somewhere else
int main() {
fifo_t fifo;
fifo_init(&fifo);
fifo_use(fifo);
fifo_free(fifo);
}
如果您只想传递指向fifo\t
的指针,那么您只能在头文件中转发声明它。但是,未命名结构的typedef
仅在定义结构的内容时有效。因此,如果您不想要struct fifo\t var代码>要编译,您必须使用一些违反直觉的名称,例如fifo\u t\u
。例如:
typedef struct fifo_t_ fifo_t;
void fifo_use(fifo_t*); // ok, just uses pointer
然后在.c
文件中,执行(请注意,使用逗号分隔成员是无效的语法):
另外,请注意fifo\t var代码>不起作用,因为您需要知道结构的大小才能为其分配空间。您可以做的是,以对用户透明的方式在内部使用指针:
// in .h file:
typedef struct fifo_t_* fifo_t;
void fifo_init(fifo_t*);
void fifo_free(fifo_t);
void fifo_use(fifo_t);
// in .c file:
struct fifo_t_{
uint8_t *buffer;
uint8_t indexRead;
uint8_t indexWrite;
uint8_t used;
uint8_t size;
};
void fifo_init(fifo_t* f) {
*f = (fifo_t)malloc(sizeof(struct fifo_t_));
}
void fifo_free(fifo_t f) {
free(f);
}
void fifo_use(fifo_t f) {
f->indexRead = 1;
}
// somewhere else
int main() {
fifo_t fifo;
fifo_init(&fifo);
fifo_use(fifo);
fifo_free(fifo);
}
如果您确实想在fifo.h中定义结构,这是一种方法:
fifo.h
...
#ifdef FIFO
typedef struct {
uint8_t *buffer,
uint8_t indexRead,
uint8_t indexWrite,
uint8_t used,
uint8_t size
} fifo_t;
#else
...
#endif
...
fifo.c
#define FIFO
#include "fifo.h"
...
因此,fifo.h仍然可以包含在其他源文件中,但结构类型是隐藏的,只有使用fifo.c才能在fifo.h中定义结构,这是一种方法:
#define FIFO
#include "fifo.h"
...
fifo.h
...
#ifdef FIFO
typedef struct {
uint8_t *buffer,
uint8_t indexRead,
uint8_t indexWrite,
uint8_t used,
uint8_t size
} fifo_t;
#else
...
#endif
...
fifo.c
#define FIFO
#include "fifo.h"
...
因此,fifo.h仍然可以包含在其他源文件中,但结构类型是隐藏的,它仅在fifo.c中可见。您不能对原始的结构本身执行此操作。您可以为指向结构的不透明指针创建typedef
?可以接受吗?实际上,您不能声明fifo\t变量
在没有完整结构定义的其他代码中,因为其他代码没有足够的信息来留出足够的内存来保存它。如果您希望只在特定的源文件中知道该结构,为什么不直接在源文件而不是头文件中定义它呢?如果您只需要少数源文件中的结构,而不是大多数源文件中的结构,那么可以选择创建一个新的“private”头文件(例如fifo_private.h
)包含此结构的文件。@ShadowRanger:Typedef'ing指针是个坏主意。@Olaf:当指针是仅由API函数创建、销毁和使用的数据的不透明句柄时?没有那么多。当指针在逻辑上不是指针,并且用户无法直接访问它所引用的数据时,隐藏它作为指针的标识是可以的。对于原始struct
本身,您无法做到这一点。您可以为指向结构的不透明指针创建typedef
?可以接受吗?实际上,您不能声明fifo\t变量
在没有完整结构定义的其他代码中,因为其他代码没有足够的信息来留出足够的内存来保存它。如果您希望只在特定的源文件中知道该结构,为什么不直接在源文件而不是头文件中定义它呢?如果您只需要少数源文件中的结构,而不是大多数源文件中的结构,那么可以选择创建一个新的“private”头文件(例如fifo_private.h
)包含此结构的文件。@ShadowRanger:Typedef'ing指针是个坏主意。@Olaf:当指针是仅由API函数创建、销毁和使用的数据的不透明句柄时?没有那么多。当指针在逻辑上不是指针,并且用户无法直接访问它所引用的数据时,可以隐藏它作为指针的标识
而不是abscuratestruct
pointer。@问题是,这样您就可以传入任何内容,并且会失去某种程度的类型安全性。结构名称中不需要尾随下划线,结构名称与联合一起位于单独的命名空间中。例如,typedef结构fifo\u t fifo\t代码>可以正常工作。我也会再次提出建议
#define FIFO
#include "fifo.h"
...