Frage Verletzung der statischen Funktion in C


In einem Interview wurde ich gefragt, ob in einer Datei A eine statische Funktion definiert ist und in der Datei B diese statische Funktion verwendet werden soll - wie wird sie benutzt?

Meine Antworten waren:

  1. Deklaration in .h-Datei Aber wenn wir dies in einer Header-Datei deklarieren, haben andere Dateien, die dies beinhalten, auch Zugriff auf diese statische Funktion.
  2. Wrapper-Konzept: Eine neue Funktion deklarieren newfun in Datei A, die statische Funktion aufruft und diese aufruft newfun in Datei B.

Aber er war mit diesen Antworten nicht zufrieden.

Kannst du mir bitte eine bessere Lösung vorschlagen, um zu verletzen? static.


6
2017-10-07 12:03


Ursprung


Antworten:


Vielleicht wollten sie von Funktionszeigern hören?

Sie können einen Zeiger auf die Funktion erstellen und ihn mit diesem Zeiger aufrufen.

Ein mögliches Szenario, in dem dies sinnvoll ist, ist, wenn Sie eine Callback-Funktion haben, die nicht von allen aufgerufen werden soll, und Sie geben den Zeiger als Argument für einige an register_callback Funktion.

Callback-Funktionen wurden häufig verwendet, um beispielsweise dem Benutzer einer GUI-API Code für das zu geben, was passieren sollte, wenn eine Schaltfläche gedrückt wird. Heutzutage ist es bei objektorientierten Sprachen üblich, Klassen unterzuklassen und Methoden wie Android zu definieren oder zu überschreiben View Klasse und die Methode OnClickListener, aber C # -Delegaten sind C-Funktionszeigern sehr ähnlich.

Um das Prinzip zu veranschaulichen, hier ist der Quellcode (die Datei "B" in der ursprünglichen Frage) für eine Art von Bibliothek, wo die Hauptkomponente ist do_stuff Funktion:

#include <stdio.h>
#include "some_library.h"

void (*stored_callback)(void) = NULL;

void register_callback(void (*callback)(void)) {
    stored_callback = callback;
}

void do_stuff(void) {
    printf("Doing stuff...\n");
    printf("Calling callback...\n");
    if (stored_callback != NULL)
        stored_callback();
}

Dieser Header, some_library.h, Datei zeigt die API dieser Bibliothek:

extern void register_callback(void (*callback)(void));
extern void do_stuff(void);

Und hier ist, wie die Bibliothek verwendet wird (die Datei "A" in der Frage):

#include <stdio.h>
#include "some_library.h"

static void my_callback(void) {
    printf("Inside the callback!\n");
}

int main(void) {
    register_callback(my_callback);
    do_stuff();
    return 0;
}

9
2017-10-07 12:15



Meine Interviewantwort wäre "Du kannst nicht".

(Weil die Frage sagt "in Datei B willst du das verwenden statisch Funktion "und es hat nicht gesagt, dass Sie Datei A ändern dürfen.)


8
2017-10-07 12:18



Ich gehe davon aus, dass Sie keinen Zugriff auf die Quelle der statischen Funktion haben, sonst könnten Sie einfach die entfernen static Schlüsselwort oder stellen Sie die Funktion über einen exportierten Wrapper oder globalen Funktionszeiger zur Verfügung.

Sie können weiterhin die statische Funktion verwenden, wenn Sie verwenden objcopy um die Sichtbarkeit des Symbols in der Objektdatei / Bibliothek manuell zu ändern.

Angenommen, dies ist die (nicht zugängliche) statische Funktion:

//static.c
#include <stdio.h>
static void fun(){
  puts("Hello world");
}

Angenommen, du hast nur static.o, erhältlich mit gcc -c static.c.

Nehmen wir nun an, Sie möchten eine Verknüpfung herstellen static.o mit main.o gemacht von

//main.c
void fun();

void main(){
  fun();
};

Um es verlinken zu können, müssen Sie sich drehen

$ nm static.o
0000000000000000 t fun
                 U puts

in

0000000000000000 T fun
                U puts

Sie können das tun mit:

objcopy --globalize-symbol=fun static.o global.o 

Jetzt können Sie mit verknüpfen global.o Anstatt von static.o.

$ gcc main.o global.o && ./a.out
  Hello world

3
2017-10-07 12:17



Dateia.c

#include <stdio.h>
#include "filea.h"
static void hidden(void) { printf("inside hidden function.\n"); }
fxptr unhide(void) { return hidden; }

filea.h

#ifndef FILEA_INCLUDED
#define FILEA_INCLUDED
typedef void(*fxptr)(void);
fxptr unhide(void);
#endif

Datei.c

#include "filea.h"
int main(void) {
    unhide()();
    return 0;
}

2
2017-10-07 12:16