C: публичные псевдонимы, чтобы скрыть статическую функцию - PullRequest
4 голосов
/ 16 января 2012

В C у меня есть функция, которая реализует процедуры шифрования и дешифрования блочного шифра.Чтобы поддерживать общее соглашение об именах и использовании и оставить открытой возможность разделения подпрограмм на две различные функции позже, я сделал следующее:

void cipher(char *out, const char *in);
#define encrypt    cipher
#define decrypt    cipher

Это прекрасно работает, за исключением того, чтоЯ действительно хотел бы скрыть фактическую функцию (cipher), чтобы люди использовали encrypt или decrypt.Прямо сейчас, cipher является частью общедоступного интерфейса, поэтому, если я решу позже разделить его на две разные функции и удалить cipher, строго говоря, я нарушаю интерфейс.Но если я могу скрыть cipher, так что только encrypt и decrypt являются частью интерфейса, я буду в порядке.

Единственный вариант, который я до сих пор придумал, это make cipher static и реализуют фактические функции для encrypt и decrypt для вызова cipher, но я не уверен, что дополнительные издержки действительно того стоят (я пытаюсь сохранить размер кода как можно более строгим,и у меня есть несколько случаев этой же проблемы).

Есть ли что-то, что я могу сделать с указателями на функции?Есть еще идеи?

Ответы [ 3 ]

2 голосов
/ 16 января 2012

Вы можете использовать функциональные указатели:

static void cipher(...);

void (*encrypt)(...) = cipher;
void (*decrypt)(...) = cipher;

По крайней мере при обычном использовании (пользователь просто использует encrypt(whatever);) это обычно не будет видно. Единственная очевидная проблема заключается в том, что, как определено выше, указатели остаются доступными для записи, поэтому вы можете захотеть сделать их const, чтобы пользователь не мог случайно перезаписать их адресом какой-либо другой функции.

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

#define encrypt(x, y) private_cipher_((x), (y))
#define decrypt(x, y) private_cipher_((x), (y))

Это должно обеспечить защиту от любых накладных расходов.

0 голосов
/ 16 января 2012

В GCC (и совместимых) землях вы также можете использовать атрибут fluff для контроля видимости символов, управления версиями и алиасами:

static void xxx_encrypt_decrypt(char *y, const char *x) { ... }
void encrypt(char *, const char *) __attribute__((alias("xxx_encrypt_decrypt")));
void decrypt(char *, const char *) __attribute__((alias("xxx_encrypt_decrypt")));
0 голосов
/ 16 января 2012

Если вы используете GCC, вы можете использовать атрибут alias , чтобы создать два псевдонима, которые указывают на вашу функцию cipher.

Но помните комментарий Стива Джессопа и подумайте над написанием двух функций-обёрток. Это не должно вызывать заметных накладных расходов. Компилятор может даже написать эти функции-обертки в виде одной инструкции перехода.

...