这是我的设置:
在public.h中:
#ifndef PUBLIC_H_
#define PUBLIC_H_
#include "func.h"
/*extern typedef struct _my_private_struct PRIVATE_;*/
typedef struct _my_private_struct PRIVATE_; /* Thanks to larsmans and Simon Richter */
#endif
在struct.h中
#ifndef STRUCT_H_
#define STRUCT_H_
struct _my_private_struct {
int i;
};
#endif
在func.h中:
#ifndef FUNC_H_
#define FUNC_H_
#include "struct.h"
/* typedef struct _my_private_struct PRIVATE_; */
extern PRIVATE_ * get_new(int);
#endif
在func.c中:
#include <stdlib.h>
#include "func.h"
PRIVATE_ * get_new(int i)
{
PRIVATE_ *p = (PRIVATE_ *) malloc(sizeof(PRIVATE_));
if (p == NULL) return NULL;
p->i = i;
return p;
}
在main.c中:
#include "public.h"
int main(int argc, char ** argv)
{
PRIVATE_ *p = get_new(2);
return 0;
}
当我用GCC编译这些文件时,我收到了这个错误:
OLD COMPILE ERROR
声明说明符中的多个存储类
编辑后的编译错误
在'*'标记之前预期'=',',',';','asm'或'__attribute__'
有人可以帮助我/解释我为什么会这样做以及如何解决这个问题?
答案 0 :(得分:6)
其他答案很好地解决了你的问题。但是,请允许我添加并回答您的最新评论:
我收到编译错误:在public.h中:重新定义typedef PRIVATE _...
虽然错误是不言自明的,但可能不太清楚为什么会这样。考虑一下当你包含public.h时会发生什么:
#include "struct.h"
#include "func.h"
typedef struct _my_private_struct PRIVATE_;
如果你追踪并完全展开预处理器,这就是你将得到的:
// struct.h
struct _my_private_struct
{
int i;
};
// func.h
typedef struct _my_private_struct PRIVATE_;
extern PRIVATE_ * get_new(int);
// public.h
typedef struct _my_private_struct PRIVATE_;
现在应该明白为什么你遇到了问题。如果没有func.h中的typedef,您的get_new
原型会失败,因为它还没有看到PRIVATE
。 OTOH,如果你保留typedef,你已经定义了两次。
此外,您似乎正在尝试将该结构与其他代码和模块保持私有。即使您确实修复了构建错误,也没有真正实现该封装。考虑一下:
int main()
{
PRIVATE_ *p = get_new(2);
p->i = 1337; // HAHA, I just modified your private i.
// what are you going to do about it?
}
如果您想在C中使用数据隐私,请考虑使用不透明的指针设计。我建议像这样重构你的来源:
// public.h
#ifndef PUBLIC_H_
#define PUBLIC_H_
#include "func.h"
#endif
// func.h
#ifndef FUNC_H_
#define FUNC_H_
struct PRIVATE_NOT_ACCESSIBLE;
typedef struct PRIVATE_NOT_ACCESSIBLE myint_t;
// declare your struct methods here
myint_t* get_new(int);
// ..
#endif
// func.c
#include <stdlib.h>
#include "func.h"
// define this only with functions
// that's suppose to work with its internal data
struct PRIVATE_NOT_ACCESSIBLE
{
int i;
};
myint_t * get_new(int i)
{
// ...
}
现在,如果你试试这个:
#include "public.h"
int main()
{
myint_t *p = get_new(2);
p->i = 1337; // Aw, doesn't work anymore :(
}
编辑:要回答以下OP的评论。
如果您在多个编译单元中实现了私有结构的方法,您仍然可以通过将私有定义移动到专用标头来使其工作:
// func_implementation.h
#include "func.h"
struct PRIVATE_NOT_ACCESSIBLE
{
int i;
};
// internal methods, helper functions you don't want exposed should go here too.
// eg.
void helper_method(myint_t *);
实现struct private'object'的源文件将包含'func_implementation.h'。使用私有的外部客户端代码仅包含'func.h'。
答案 1 :(得分:5)
typedef
;
声明
extern typedef
没有意义,只需要typedef
。答案 2 :(得分:2)
当前语法不正确,您需要在typedef和structs之后加一个分号。
答案 3 :(得分:1)
有一个';'在typedef之后丢失。
编辑:
struct _my_private_struct {...};
不要使用带有前导下划线的名称。它们保留用于语言或实现。