Guten Tag,
Ich habe eine Verständnisfrage zu Funktionszeigern im Struct.
Wenn Ich ein Funktionsprototyp im Strukt-Bereich anlegen will, kann Ich
da den Prototyp als Funktionszeiger definieren oder muss Ich den
Funktionszeiger definieren und dem Prototyp zuweisen?
Mein Ziel ist es, eine Bibliothek anzulegen, bei der man durch den
Struct-Bezeichner, die Libary erkennen kann (z.B. UART.xy oder I2C.xz)
Beispiel:
1
//Header einer Libary:
2
3
typedefstruct
4
{
5
void(*test)(void);
6
}Funktionsstruktur;
7
8
//C-Datei einer Libary:
9
10
voidtest(void)
11
{
12
//Lorem Ipsum
13
}
In der Main-Datei
1
//Main.h:
2
3
#include"Libary.h";
4
5
//C-Datei der Main (innerhalb der while(1)-Schleife):
>Wenn Ich ein Funktionsprototyp im Strukt-Bereich anlegen will, kann Ich>da den Prototyp als Funktionszeiger definieren oder muss Ich den>Funktionszeiger definieren und dem Prototyp zuweisen?
Weder noch.
Du kannst in einer Strukturdefinition keinen Prototyp deklarieren noch
einen Prototyp als Zeiger auf eine Funktion definieren noch einen
Funktionszeiger einem Prototypen zuweisen.
Die Begriffe "definieren", "deklarieren" und "Funktionsprototyp" sowie
"Struktur" haben im Kernighan&Ritchie, sprich: der Sprachdefinition
genau festgelegte Bedeutungen.
Lies sie bitte einmal nach und formulieren Deine Fragen neu.
Aber, in Kürze, folgendes:
Ein "Funktionsprototyp" ist teilt dem Compiler Namen, Parameter und
Rückgabewert einer später im Quelltext verwendeten Funktion mit. Es
handelt sich im engeren Sinn um eine Deklaration. Der Text eines
Prototypen kann syntaktisch nicht in einer Strukturdeklaration
erscheinen, also kann man nicht: "ein Funktionsprototyp im
Strukt-Bereich anlegen".
Da also in einer Strukturdeklaration kein Prototyp deklariert werden
kann, erübrigt sich die Frage danach, ob das als Funktionszeiger möglich
ist.
Eine Strukturbeschreibung, die mit "typedef" eingeleitet wird ist ebenso
eine Deklaration. Ein darin erscheinender Funktionszeiger ist damit also
nicht "definiert" sondern "deklariert".
Kleine Merkregel: Eine "Definition" belegt Speicherplatz. Du kannst also
in einer Strukturdeklaration nicht "zuweisen". Es gibt ja keine
Speicherplatz der die Zuweisung speichern könnte.
Dennoch geht, was Du vorhast. Deklariere Strukturen mit
Funktionszeigern, definiere eine Variable mit dieser Struktur und
initialisiere sie mit den Funktionszeigern auf die jeweilige Funktion.
Kleiner Hinweis: Das Problem, das nämlich zwei gleichnamige Funktionen
aus einer I2C- und einer UART-Library einen Name-Clash, also eine
Fehlermeldung des Linkers, ergeben, wird sich aber so nicht lösen
lassen. Die Funktionsnamen sind, ohne weitere Maßnahmen grundsätzlich
global bekannt.
Hmm schrieb:> Kleiner Hinweis: Das Problem, das nämlich zwei gleichnamige Funktionen> aus einer I2C- und einer UART-Library einen Name-Clash, also eine> Fehlermeldung des Linkers, ergeben, wird sich aber so nicht lösen> lassen. Die Funktionsnamen sind, ohne weitere Maßnahmen grundsätzlich> global bekannt.
Wie die Funktionen heißen kann er ja selber festlegen.
i2c_Send();
wie sie in der Struktur heißen kann ja anders sein. Dann könnte man sie
auch noch als Static deklarieren, dann werden sie nicht exportiert.
Aber wo soll nun der Vorteil sein ob man schreibt.
i2c_Send();
oder
i2c.Send();
Hmm schrieb:> Kleiner Hinweis: Das Problem, das nämlich zwei gleichnamige Funktionen> aus einer I2C- und einer UART-Library einen Name-Clash, also eine> Fehlermeldung des Linkers, ergeben, wird sich aber so nicht lösen> lassen. Die Funktionsnamen sind, ohne weitere Maßnahmen grundsätzlich> global bekannt.
In gewisser Weise schon. Mit diesem Ansatz können die Funktionen
statisch und dennoch anderswo aufrufbar sein. Ob das sinnvoll ist wär
allerdings eine andere Frage.
>In gewisser Weise schon. Mit diesem Ansatz können die Funktionen>statisch und dennoch anderswo aufrufbar sein.
Was heisst "in gewisser Weise"? Entweder sind Funktionen global sichtbar
oder nicht.
Eine Strukturdeklaration ändert daran nichts. Man müsste auch die
Funktionen umbenennen oder als static deklarieren.
Und was heisst "statisch aufrufbar"? Eine solche Kategorie gibt es
meiner Kenntnis nach nicht in C.
Hallo Hmm,
Vielen Dank für deine Antwort, Ich war gerade etwas durch den Wind bzgl.
Definierung und Deklaration.
Wenn Ich dich jetzt richtig verstanden habe, dann muss ich dem
Funktionspointer eine existierende Funktion zuweisen (diese hat einen
vorhandenen Funktionsprototypen in der Datei/Header)
Also z.B.
Hmm schrieb:> Was heisst "in gewisser Weise"? Entweder sind Funktionen global sichtbar> oder nicht.
Es gibt da auch eine Zwischenform. Die Funktionsnamen sind nicht global
sichtbar (weil "static"), aber die Funktionen sind über solche Zeiger
dennoch ausserhalb des Moduls aufrufbar.
> Und was heisst "statisch aufrufbar"?
Keine Ahnung, ich habe das nirgends geschrieben.
Hmm schrieb:> Was heisst "in gewisser Weise"? Entweder sind Funktionen global sichtbar> oder nicht.> Eine Strukturdeklaration ändert daran nichts.
doch es ändert was daran.
wenn eine Funktion static ist, dann kann sie von außen nicht aufgerufen
werden. Wenn aber in einer extern deklarierten Struktur ein
Funktionszeiger auf diese Funktion vorhanden ist, kann sie aufgerufen
werden.