непрозрачные (абстрактные) типы данных в C - PullRequest
0 голосов
/ 04 января 2010

Файл api.h

#include <stdio.h>
#ifndef API
#define API

struct trytag;
typedef struct trytag try;

void trial (try *);

#endif

Файл core.h

#ifndef CORE
#define CORE
struct trytag
{
    int a;
    int b;
};
#endif

Файл func.c

#include "api.h"
#include "core.h"

void trial (try *tryvar)
{
    tryvar->a = 1;
    tryvar->b = 2;
}

Файл main.c

#include "api.h"

int main ()
{
    try s_tryvar;

    trial(&s_tryvar);

    printf("a = %d\nb = %d\n", s_tryvar.a, s_tryvar.b);
}

Когда я компилирую, я получаю:

main.c:5: error: storage size of ‘s_tryvar’ isn’t known

Если я включу core.h в main.c, эта ошибка не возникает, поскольку try определен в core.h. Но я хочу, чтобы структура try была скрыта для main.c - она ​​не должна знать членов структуры try. Чего мне не хватает?

Ответы [ 4 ]

6 голосов
/ 04 января 2010

Я не думаю, что вы пытаетесь сделать это возможно. Компилятор должен знать, насколько велика структура try для компиляции main.c. Если вы действительно хотите, чтобы он был непрозрачным, создайте универсальный тип указателя и вместо объявления переменной непосредственно в main() сделайте функции alloc_try() и free_try() для обработки создания и удаления.

Примерно так:

api.h:

#ifndef API
#define API

struct trytag;
typedef struct trytag try;

try *alloc_try(void);
void free_try(try *);
int try_a(try *);
int try_b(try *);
void trial (try *);

#endif

core.h:

#ifndef CORE
#define CORE
struct trytag
{
    int a;
    int b;
};
#endif

func.c:

#include "api.h"
#include "core.h"
#include <stdlib.h>

try *alloc_try(void)
{
    return malloc(sizeof(struct trytag));
}

void free_try(try *t)
{
    free(t);
}

int try_a(try *t)
{
    return t->a;
}

int try_b(try *t)
{
    return t->b;
}

void trial(try *t)
{
    t->a = 1;
    t->b = 2;
}

main.c:

#include <stdio.h>
#include "api.h"

int main()
{
    try *s_tryvar = alloc_try();

    trial(s_tryvar);
    printf("a = %d\nb = %d\n", try_a(s_tryvar), try_b(s_tryvar));

    free_try(s_tryvar);
}
1 голос
/ 04 января 2010

Проблема в main.c, компилятор не видел определения struct try.Из-за этого компилятор ограничен использованием указателей на struct try.

. То, что вы хотите сделать, это добавить две новые функции в ваш API:

try *create_try();
void *destroy_try(try *t);

Эти функции будут вызывать mallocи соответственно бесплатно.

Если вы не хотите ограничивать свою структуру только разрешением в куче, вам придется отказаться от того, чтобы сделать ее непрозрачной.

1 голос
/ 04 января 2010

Подумайте, как работает непрозрачная структура FILE в C. Вы работаете только с указателями, и вам нужна функция типа fopen () для создания экземпляра и функция типа fclose () для его удаления.

0 голосов
/ 01 ноября 2015

Существует способ сделать что-то, что технически не совсем то, о чем вы просите, но должно служить той же цели - сохранить непрозрачность вашей структуры при поддержке распределения без кучи.

в api.h указывается непрозрачная структура следующим образом:

struct trytag_opaque
{
    char data[sizeof(int)*2];
};

если вы хотите быть более непрозрачным, вы можете рассчитать максимальный размер структуры, требуемый для любой поддерживаемой платформы, и использовать:

struct trytag_opaque
{
    char data[MAX_TRYTAG_SIZE];
};

Тогда ваши объявления функций api.h будут выглядеть так:

int try_a(struct trytag_opaque *t)

и ваш код функции будет выглядеть так:

int try_a(struct trytag_opaque *t_opaque) {
    trytag *t = (trytag *)t_opaque;
    ...
}

и ваш main.c будет выглядеть так:

#include "api.h"
int main() {
    struct trytag_opaque t;
    ...
    try_a(&t);
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...