2009-09-09 14 views
22

Zostałem poproszony o bardzo interesujące pytanie podczas wywiadu C: Jak można zaimplementować funkcję f() w taki sposób, że można ją wywołać tylko z konkretnej funkcji g(). Jeśli funkcja inna niż g() spróbuje wywołać f(), spowoduje to błąd kompilatora.Jak zaimplementować funkcję "private/restricted" w C?

Na początku, mogłem to zrobić za pomocą wskaźników funkcji i mogłem zbliżyć się do zablokowania połączenia w czasie wykonywania. Ale nie byłem w stanie wymyślić strategii czasu kompilacji. Nie wiem nawet, czy jest to możliwe przy użyciu ansi C.

Czy ktoś ma jakiś pomysł?

+0

Czy na pewno pytanie było dokładnie takie jak to? To nie ma dla mnie żadnego sensu. Być może, gdyby dotyczyło to funkcji członka, to może miałoby to jakieś zalety, ale zwykłe funkcje? – Suma

+0

@Suma: Nie będzie funkcji członka w C. –

Odpowiedz

23

Umieść g() i f() w tym samym module i zadeklaruj f() jako statyczny. Statyczne słowo kluczowe sprawia, że ​​f() jest dostępne tylko dla funkcji w tym samym module lub pliku źródłowym.

Można również wspomnieć, że w module nie można stosować innych metod za pomocą f() i g(), w przeciwnym razie mogą wywołać funkcję f().

PS - Naprawdę uważam, że odpowiedź Chrisa Lutza jest w rzeczywistości najlepsza. Wymienia to podejście, ale także sprytną zmianę nazwy makra, która działa przy mniejszej liczbie warunków środowiskowych (nie wymaga pliku modułu specjalnie dla tych dwóch funkcji).

Należy również zauważyć, że z makra, można wykonać następujące czynności:

#define f() f_should_not_be_called_by_anything_except_g 

Które zaprezentować piękny komunikat o błędzie, samochodowa i ukończyły (jak Visual Studio), by pokazać, że wskazówka gdy użytkownik wpisze f().

+1

Sprawdź komentarz zrobiłem @ Jan Milikin. – luizleroy

+0

Jestem świadomy. Naprawdę łatwe do naprawienia. –

+0

Właściwie jestem fanem odpowiedzi Jonathana Lefflera, ale jak powiedział, nie można jej uogólniać. Ale awansowałem prawie na każdego, kto powiedział poprawną odpowiedź (tzn. 'Static' function). Prawdopodobnie tego, czego szukali. –

8

Umieść f() i g() w tym samym pliku źródłowym, zadeklaruj f() statyczny.

+1

Nie sądzę, że to oczekiwana odpowiedź. Nie powstrzymuje to nikogo przed umieszczaniem innych funkcji w tym samym źródle i cal f(). – luizleroy

+17

Każdy, kto może edytować twoją funkcję źródłową, może przezwyciężyć * dowolny * schemat tworzenia czegoś prywatnego. – dmckee

33

Oto jeden ze sposobów:

int f_real_name(void) 
{ 
    ... 
} 

#define f f_real_name 
int g(void) 
{ 
    // call f() 
} 
#undef f 

// calling f() now won't work 

Innym sposobem, jeśli można zagwarantować, że f() i g() to jedyne funkcje w pliku, to zadeklarować f() jak static.

EDIT: Kolejny makro trik powodować błędy kompilatora:

static int f(void) // static works for other files 
{ 
    ... 
} 

int g(void) 
{ 
    // call f() 
} 
#define f call function 

// f() certainly produces compiler errors here 
+1

Jednak nadal możesz zadzwonić do f_real_name(). –

+1

Jest to prawda, ale nie jest to bezwzględnie wymagane. Graj zgodnie z zasadami, a nie intencjami. –

+3

Oczywiście możemy nazwać 'f_real_name()'. Możemy również nazwać 'printf()', 'malloc()' i wiele innych fajnych funkcji, ale co to ma wspólnego z wywołaniem 'f()'? –

10

Można dokonać funkcje modułu-prywatnego z static słów kluczowych:

static void func(void) 
{ 
    // ... 
} 

Następnie, func() można nazwać tylko przez inne funkcje zdefiniowane w tym samym pliku (technicznie, ta sama jednostka tłumacząca : inne funkcje, których definicje są zawarte w dyrektywie #include, mogą nadal uzyskiwać dostęp to). Mówi się, że func ma wewnętrzny łącznik . Wszystkie pozostałe funkcje (tj. Bez słowa kluczowego static) mają połączenie z zewnętrznym.

Poza tym, nie ma sposobu, aby uniemożliwić dostęp do funkcji. Możesz użyć makr, aby zmienić nazwę funkcji, ale inny kod zawsze może uzyskać do niej dostęp z odpowiednią nazwą.

2

Jest to możliwe tylko przypadkowo.

Jeśli funkcje f() i g() znajdują się w tym samym pliku źródłowym i nie ma żadnych innych funkcji w pliku, a jeśli g() nigdy nie zwraca wskaźnika funkcji do f() do żadnego z jego wywołań , a następnie wykonanie f() static wykona zadanie.

Jeśli inne funkcje muszą pojawić się w tym samym pliku źródłowym, umieszczając f() na dole pliku jako funkcję statyczną i definiując tylko g() natychmiast po uzyskaniu mniej więcej takiego samego efektu - chociaż jeśli nie powiedzieliście kompilatorowi, aby generował błędy w "brakujących deklaracjach", inne funkcje mogłyby wywoływać je z ostrzeżeniami.

#include <stdio.h> 

extern void g(void); /* in a header */ 

/* Other functions that may not call f() go here */ 

static void f(void) 
{ 
    puts("X"); 
} 

void g(void) 
{ 
    f(); 
} 

Oczywiście, ta technika nie może być rozszerzony niezawodnie inną parę funkcji w tym samym pliku - X() i y() - takie, że x() i tylko x() może wywołać Y() po g() i tylko g() może wywołać f() w tym samym czasie.

Zwykle jednak polegasz na dyscyplinie programistów i po prostu ustaw f() w pliku źródłowym wraz z komentarzem, który może wywołać tylko g(), a następnie zdyscyplinować każdego, kto modyfikuje kod tak, aby funkcja inna niż g() wywołuje f().

Powiązane problemy