2009-09-09 14 views
22

In einem C-Interview wurde mir eine sehr interessante Frage gestellt: Wie kann man eine Funktion f() so implementieren, dass sie nur aus einer bestimmten g() -Funktion aufgerufen werden kann? Wenn eine andere Funktion als g() versucht, f() aufzurufen, würde dies zu einem Compilerfehler führen.Wie implementiert man eine "private/restricted" -Funktion in C?

Zuerst konnte ich das mit Funktionszeigern machen und ich könnte den Aufruf zur Laufzeit blockieren. Aber ich konnte mir keine Kompilierzeit-Strategie vorstellen. Ich weiß nicht einmal, ob das mit Ansi C möglich ist.

Hat jemand eine Idee?

+0

Sind Sie sicher, dass die Frage genau so war? Es ergibt keinen Sinn für mich. Wenn es vielleicht um Mitgliederfunktionen geht, könnte es vielleicht etwas Verdienst haben, aber gewöhnliche Funktionen? – Suma

+0

@Suma: Es würde keine Mitgliedsfunktionen in C geben. –

Antwort

23

Setzen Sie g() und f() in dasselbe Modul und deklarieren Sie f() als statisch. Das static-Schlüsselwort macht f() nur für Funktionen im selben Modul oder in derselben Quelldatei verfügbar.

Sie möchten vielleicht auch erwähnen, dass keine anderen Methoden im Modul mit f() und g() erlaubt sein sollten, sonst könnten sie f() aufrufen.

PS - Ich glaube wirklich, Chris Lutz 'Antwort ist eigentlich die beste. Es erwähnt diesen Ansatz, aber auch eine clevere Makroumbenennung, die mit weniger Umgebungsbedingungen arbeitet (erfordert nicht die Moduldatei speziell für diese beiden Funktionen).

Beachten Sie auch, dass mit einem Makro, könnten Sie Folgendes tun:

#define f() f_should_not_be_called_by_anything_except_g 

was eine nette Fehlermeldung darstellen würde, und auto-Beender (wie Visual Studio), dass die Spitze zeigen würde, wenn der Benutzer f().

+1

Überprüfen Sie den Kommentar, den ich @John Milikin gemacht habe. – luizleroy

+0

Ich bin mir bewusst. Ziemlich einfach zu reparieren, wirklich. –

+0

Eigentlich bin ich ein Fan von Jonathan Lefflers Antwort, aber wie er sagte, ist es nicht verallgemeinerbar. Aber ich habe fast jeden, der die richtige (d. H. "Statische" Funktion) Antwort gesagt hat, aufgewertet. Wahrscheinlich wonach sie gesucht haben. –

8

Platzieren Sie f() und g() in der gleichen Quelldatei, deklarieren Sie f() statisch.

+1

Ich denke nicht, dass das die erwartete Antwort ist. Dies hindert niemanden daran, andere Funktionen in dieselbe Quelle und denselben cal f() zu stellen. – luizleroy

+17

Jeder, der Ihre Source-Funktion bearbeiten kann, kann ein * beliebiges * Schema für etwas Privates umgehen. – dmckee

33

Hier ist eine Art und Weise:

int f_real_name(void) 
{ 
    ... 
} 

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

// calling f() now won't work 

Eine andere Möglichkeit, wenn Sie garantieren können, dass f() und g() die einzigen Funktionen in der Datei sind, ist f() als static zu erklären.

EDIT: Ein anderer Makro Trick Compiler-Fehler verursachen:

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

Sie können jedoch weiterhin f_real_name() aufrufen. –

+1

Das ist richtig, aber nicht unbedingt eine Voraussetzung. Spiele nach den Regeln, nicht nach den Absichten. –

+3

Natürlich können wir 'f_real_name()' aufrufen. Wir können auch 'printf()', 'malloc()' und viele andere nette Funktionen aufrufen, aber was hat es mit dem Aufruf von 'f()' zu tun? –

10

Sie können Modul-privaten Funktionen mit dem static Stichwort machen:

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

Dann func() kann nur von anderen Funktionen aufgerufen werden in der gleichen Datei definiert (technisch, die gleiche Übersetzungseinheit: andere Funktionen, deren Definitionen sind enthalten durch eine #include Richtlinie kann immer noch zugreifen es). func soll interne Verknüpfung haben. Alle anderen Funktionen (dh ohne das Schlüsselwort static) sollen externe Verknüpfung haben.

Darüber hinaus gibt es keine Möglichkeit, Funktionen unzugänglich zu machen. Sie können Makros verwenden, um den Namen der Funktion zu ändern, aber anderer Code kann immer noch mit dem entsprechenden Namen darauf zugreifen.

2

Es ist nur zufällig möglich.

Wenn sich die Funktionen f() und g() beide in derselben Quelldatei befinden und keine anderen Funktionen in der Datei vorhanden sind und wenn g() den Funktionszeiger an f() niemals an einen der Aufrufer zurückgibt Dann macht f() static den Job.

Wenn andere Funktionen in derselben Quelldatei angezeigt werden müssen, platzieren Sie f() am unteren Ende der Datei als statische Funktion, und definieren Sie g() unmittelbar danach, um mehr oder weniger den gleichen Effekt zu erzielen Sie haben dem Compiler nicht gesagt, dass er Fehler bei "fehlenden Deklarationen" erzeugen soll, andere Funktionen könnten ihn mit Warnungen aufrufen.

#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(); 
} 

Verständlich kann diese Technik nicht zuverlässig in derselben Datei ein anderes Paar von Funktionen erweitert werden - x() und y() -, so daß x() und nur x() kann y(), während g nennen() und nur g() kann f() gleichzeitig aufrufen.

Normalerweise würden Sie sich jedoch auf die Disziplin der Programmierer verlassen und einfach f() statisch in der Quelldatei zusammen mit einem Kommentar machen, den nur g() aufrufen darf, und dann jeden disziplinieren, der den Code so ändert Eine andere Funktion als g() ruft f() auf.

8

Eine Option für GCC ist die Verwendung nested functions. Es ist zwar kein Standard-C, aber es funktioniert ganz gut.

Verwandte Themen