2

这是我的设置:

在 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 编译这些文件时,我收到了这个错误:

旧编译错误

声明说明符中的多个存储类

编辑后编译错误

'*' 标记之前应有 '='、','、';'、'asm' 或 '__attribute__'

有人可以帮助我/解释我为什么会得到这个以及如何解决它吗?

4

4 回答 4

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 *);

实现您的结构私有“对象”的源文件将包括“func_implementation.h”。使用私有的外部客户端代码将仅包含“func.h”。

于 2011-12-05T01:09:34.527 回答
5
  • 您必须typedef;
  • extern typedef没有意义,只是做一个typedef.
于 2011-12-04T19:29:27.410 回答
2

当前语法不正确,您需要在 typedefs 和 structs 之后放置一个分号。

于 2011-12-04T19:29:51.607 回答
1

有一个';' 在 typedef 之后丢失。

编辑:

struct _my_private_struct {...};

不要使用带有前导下划线的名称。它们是为语言或实现保留的。

于 2011-12-04T19:34:11.927 回答