Verständnisfrage zu Funktionszeigern im Struct

Gast #3213747
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();
Gast #3213761
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.
Gast #3213766
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.
Gast #3213768
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();
#3213771
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.
Gast #3213774
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.
Gast #3213786
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?
#3213789
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.
Gast #3213790
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren