Другие ответы очень хорошо освещают вашу проблему. Тем не менее, позвольте мне добавить к ним и ответить на ваш последний комментарий:
Я получаю ошибку компиляции: в 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_;
Теперь должно быть очевидно, почему вы сталкиваетесь с проблемами. Без typedef в func.h ваш 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 :(
}
Редактировать: Чтобы ответить на комментарий ОП ниже.
Если у вас есть методы приватной структуры, реализованные в более чем одном модуле компиляции, вы все равно можете заставить его работать, перенеся определение приватной команды в выделенный заголовок:
// 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'. Код внешнего клиента, который использует private, будет включать только func.h.