Forum: Compiler & IDEs Verständnisfrage zu Funktionszeigern im Struct


von Technik_Freak (Gast)


Lesenswert?

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
typedef struct
4
{
5
    void (*test) (void);
6
}Funktionsstruktur;
7
8
//C-Datei einer Libary:
9
10
void test(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):
6
7
Funktionsstruktur.test();

von Hmm (Gast)


Lesenswert?

>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.

von Hmm (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Hmm (Gast)


Lesenswert?

>Wie die Funktionen heißen kann er ja selber festlegen.
Oder auch nicht. Darüber wissen wir ja nichts. Oder hast Du privaten 
Kontakt zum TO?

von Hmm (Gast)


Lesenswert?

>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.

von Technik_Freak (Gast)


Lesenswert?

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.
1
void funktion(void);
2
3
struct abc
4
{
5
    void (*test)(void);
6
}
7
8
void funktion(void)
9
{
10
//Lorem Ipsum
11
}
12
13
struct abc meine_variable;
14
15
meine_variable.test = funktion;

Ist dieser Ansatz richtig?

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.