it-swarm.com.de

Wie implementiere ich eine "private/restricted" Funktion in C?

Während eines C-Interviews wurde mir eine sehr interessante Frage gestellt: Wie kann man eine Funktion f() so implementieren, dass sie nur von einer bestimmten Funktion g() aufgerufen werden kann? . Wenn eine andere Funktion als g() versucht, f() aufzurufen, würde dies zu einem Compilerfehler führen.

Zuerst dachte ich, dies könnte mit Funktionszeigern geschehen und ich könnte fast den Aufruf zur Laufzeit blockieren. Aber ich konnte mir keine Strategie für die Kompilierungszeit vorstellen. Ich weiß nicht mal, ob das mit ansi C möglich ist.

Hat jemand eine Idee?

27
luizleroy

Hier ist ein Weg:

int f_real_name(void)
{
    ...
}

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

// calling f() now won't work

Wenn Sie außerdem garantieren können, dass f() und g() die einzigen Funktionen in der Datei sind, können Sie f() als static deklarieren.

BEARBEITEN: Ein weiterer Makro-Trick, der Compiler-Fehler verursacht:

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

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

// f() certainly produces compiler errors here
37
Chris Lutz

Fügen Sie g() und f() in dasselbe Modul ein und deklarieren Sie f() als statisch. Das statische Schlüsselwort macht f() nur für Funktionen in demselben Modul oder derselben Quelldatei verfügbar.

Vielleicht möchten Sie auch erwähnen, dass mit f() und g () keine anderen Methoden im Modul erlaubt sein dürfen, andernfalls könnten sie f () aufrufen.

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

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

#define f() f_should_not_be_called_by_anything_except_g

Welches eine Nice-Fehlermeldung darstellen würde, und Auto-Completers (wie Visual Studio) würden diesen Tipp anzeigen, wenn der Benutzer f () eingibt.

26
Walt W

Mit dem Schlüsselwort static können Sie Modul-private Funktionen erstellen:

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

Dann kann func() nur von anderen Funktionen aufgerufen werden, die in derselben Datei definiert sind (technisch kann dieselbe translation unit : andere Funktionen, deren Definitionen in einer #include-Direktive enthalten sind, immer noch darauf zugreifen). Man sagt, dass func interne Verknüpfung hat. Alle anderen Funktionen (dh ohne das Schlüsselwort static) sollen external linkage 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.

10
Adam Rosenfield

Eine Option für GCC ist die Verwendung von geschachtelten Funktionen . Obwohl es kein Standard-C ist, funktioniert es ziemlich gut.

8
outis

Platzieren Sie f() und g() in derselben Quelldatei, und erklären Sie f() statisch.

8
John Millikin

Das ist nur zufällig möglich.

Wenn sich die Funktionen f() und g() in derselben Quelldatei befinden und keine anderen Funktionen in der Datei vorhanden sind und wenn g() Setzt den Funktionszeiger niemals auf f() an einen seiner Aufrufer zurück, und dann wird f() static ausgeführt, um den Job auszuführen.

Wenn andere Funktionen in derselben Quelldatei enthalten sein müssen, platzieren Sie f() am Ende der Datei als statische Funktion, und definieren Sie g() erst unmittelbar danach, wenn mehr erreicht wird oder weniger der gleiche Effekt - wenn Sie dem Compiler jedoch nicht mitgeteilt haben, dass er Fehler bei 'fehlenden Deklarationen' generiert, können andere Funktionen dies 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();
}

Natürlich kann diese Technik nicht zuverlässig auf ein anderes Funktionspaar in derselben Datei erweitert werden - x() und y() - so dass x() und Nur x() kann y() aufrufen, während g() und nur g() f() zur gleichen Zeit.

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

2

Du kannst das

//some code ...
//You Can't call f() in here - compile time error
//some code ...
void f()
{
    //implement f() in here
}
void g()
{
    //You can only call f() in here - no error
}
#define f() Gimme some ERRORS!!!
//some code ...
//You Can't call f() in here - compile time error
//some code ...
0
Tomer Wolberg