Скрыть определение типа в C - PullRequest
0 голосов
/ 14 февраля 2012

У меня есть файл .c (библиотека функций) с функцией и определением, подобным этому:

typedef long double big;
big foo(int x) { ... }

Я хочу создать интерфейс этой библиотеки, .h. Итак, я делаю:

typedef long double big;
big foo(int);

и удалите typedef long double big; из файла .c. Но при этом я даю определение типа big в моем интерфейсе, так что это не совсем чистый интерфейс. Есть идеи как это исправить?

Я знаю, что могу сделать это в моем .c файле:

struct foo {
  long double;
};

и затем в файле .h выполните:

typedef struct foo big;
big foo(int);

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

Ответы [ 2 ]

4 голосов
/ 14 февраля 2012

Если тип никогда не станет более сложным, чем long double, то, вероятно, не стоит иметь намерений скрывать его больше. Если это может потребоваться усложнить, тогда вы можете рассмотреть возможность использования непрозрачного типа. В вашем общедоступном заголовке big.h вы используете:

#ifndef BIG_H_INCLUDED
#define BIG_H_INCLUDED
typedef struct big big_t;

extern big_t *foo(int);

...

#endif

Все функции будут принимать и возвращать указатели на тип big_t. Это все, что вы можете сделать с такими неполными типами. Обратите внимание, что ваши клиенты не могут выделять для себя какие-либо значения big_t; они не знают, какой размер у этого типа. Это означает, что вы, вероятно, в конечном итоге с такими функциями, как:

extern big_t *big_create(void);
extern void   big_destroy(big_t *value);

для создания и уничтожения big_t значений. Тогда они смогут выполнять арифметику с:

extern big_errno_t big_add(const big_t *lhs, const big_t *rhs, big_t *result);

Etc. Но поскольку они имеют только непрозрачный, неполный тип, они не могут надежно возиться внутри структуры big_t. Но обратите внимание, что вы ограничены использованием указателей в интерфейсе. Для передачи или возврата значений требуются полные типы, и если тип полон, пользователи могут исследовать его внутреннюю работу.

В заголовке реализации bigimpl.h вы получите:

#ifndef BIGIMPL_H_INCLUDED
#define BIGIMPL_H_INCLUDED
#include "big.h"

struct big
{
    ...whatever the details actually are...
};

#endif

И ваш код реализации будет включать только bigimpl.h, но это включает big.h. Основная проблема здесь - убедиться, что вы знаете, как распределяются выделения памяти.

Иногда эта техника стоит того. Часто это не совсем необходимо. Вам нужно будет сделать оценку для себя.

2 голосов
/ 14 февраля 2012

и удалите typedef long double big; из .c файла. Но тем самым я даю определение типа big в своем интерфейсе, так что это не совсем чистый интерфейс.

Как так? Кому интересно, увидят ли пользователи вашего кода typedef? Как это больно ... что-нибудь? Им нужен способ использовать ваш typedef, и вот как это делается. Похоже, теоретическая проблема для меня, которая не имеет заметных побочных эффектов. Вы беспокоитесь о не тех вещах.

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

Да, это глупо. Кроме того, теперь вы дали определение вашей структуры! о нет! Чем это отличается от предоставления typedef (или любого другого типа)?

...