Strukturenaufruf wie Funktion

Gast #2692834
Lesenswert?

1
name4->name2(name4,name7);  
2

3

4
typedef struct structname {
5
  void *name1;
6
  type name2;
7
  uchar name3;  
8
} tstructname;
9

10
typedef void (*type) (const struct structname * name5, char *name6);
11

12
extern const tstructname *name4;

als ich habe vollgenden Programcode bekommen und verstehe ihn nicht. ich 
mus leider zugeben das ich nicht der Beste Programmierer bin, hoffe aber 
das ihr mir helfen könnt es zu verstehen.

Die erste Zeile steht in meiner .c Datei der rest in der .h. für mich 
sah im ersten moment zeile 1 aus wie ein Funktionsaufruf. Scheint aber 
keiner zu sein. Sondern irgend ein "Sonderding" bei strukturen.

Ich danke euch für eure Hilfe
Moderator #2692844
Lesenswert?

Jürgen schrieb:
> Die erste Zeile steht in meiner .c Datei der rest in der .h. für mich
> sah im ersten moment zeile 1 aus wie ein Funktionsaufruf. Scheint aber
> keiner zu sein.

Doch, es ist einer. Schlag mal in deinem C-Buch das Kapitel "Funktions-
zeiger" bzw. "Functon Pointers" auf.

> Sondern irgend ein "Sonderding" bei strukturen.

Mit Strukturen hat das nur insofern etwas zu tun, dass der Funktionszei-
ger name2 Element einer Struktur (structname) ist. Er könnte aber auch
eine eigenständige Variable sein.
Gast #2692890
Lesenswert?

Ich verstehe es leider noch nicht.

Also was ich denke / hoffentlich verstehe ist:

1) ich lege eine struktur mit drei "Variablen" an.
   name1, name2, name3.
1
const tstructname *name4 = NULL;
   so habe ich das im Code gefunden.

2) in name3 kann ich ein char abspeichern.

3) name1 ist ein zeiger auf eine Variable

was verbirgt sich jetzt hinter name2 ?

mit
1
 name4->name2(name4,name7);
 schreibe ich in meine Instanz name4 an die Stelle name2 was? Ich 
übergebe nur zwei Zeiger? Name5 und name 6
#2692907
Lesenswert?

Jürgen schrieb:

> was verbirgt sich jetzt hinter name2 ?

Ein Zeiger auf eine Funktion.
In name2 steht die Adresse einer Funktion. Die kann man aufrufen.


>
> mit
1
 name4->name2(name4,name7);
 schreibe ich in meine Instanz
> name4 an die Stelle name2 was? Ich übergebe nur zwei Zeiger? Name5 und
> name 6

du bist völlig falsch.

name4 ist ein Zeiger auf ein structur Objekt.
Dieses Strukturobjekt hat ein paar Member. Einen undefinierten (da void) 
Pointer, der überallhin zeigen kann, solange es nur Daten sind. Einen 
uchar. Und eben auch einen Zeiger auf eine Funktion.

Und genauso, wie man auf den uchar zugreift:
   name4->name3 = 'a';
   j = name4->name3;
um ihm etwas zuzuweisen bzw den dort abgespeicherten Wert zu holen, 
genauso spezifiziert man dann eben mit

   name4->name2

erst mal den Funktionspointer. So, was macht man damit? Man kann ihm zb 
die Adresse einer Funktion zuweisen

void meine_Funktion( const struct structname * name5, char *name6 )
{
  ...
}

    name4->name2 = meine_Funktion;


oder aber man kann die Funktion auch aufrufen

   name4->name2(       );

und da die Funktion 2 Argumente haben will, einen Pointer auf ein const 
structname und einen char Pointer, gibt man die dann eben beim Aufruf 
an.

Hättest du meine_Funktion direkt aufgerufen, hättest du das auch müssen

   meine_Funktion( iregendwas, irgendwas_anderes );

beim indirekten AUfruf über einen Funktionszeiger ist das auch nicht 
anders

   name4->name2( irgendwas, irgendwas_anderes );


Wie oben schon gesagt: Dein C Buch sollte das ganze noch wesentlich 
ausführlicher beschreiben.
Moderator #2692941
Lesenswert?

... schrieb:
> Da kann man auch schon mal durcheinander kommen, wenn alles "name"x
> heißt. Darum ist es guter Stil, die Namen so zu wählen, dass man gleich
> die Bedeutung/Funktion erkennt.

Da der Code nicht von Jürgen selbst stammt, vermute ich, dass da
ursprünglich andere Namen standen, aus denen die Funktion der einzelnen
Typen, Variablen und Elemente deutlicher hervorgegangen ist.
#2692947
Lesenswert?

Yalu X. schrieb:
> ... schrieb:
>> Da kann man auch schon mal durcheinander kommen, wenn alles "name"x
>> heißt. Darum ist es guter Stil, die Namen so zu wählen, dass man gleich
>> die Bedeutung/Funktion erkennt.
>
> Da der Code nicht von Jürgen selbst stammt, vermute ich, dass da
> ursprünglich andere Namen standen, aus denen die Funktion der einzelnen
> Typen, Variablen und Elemente deutlicher hervorgegangen ist.

Das hoffe ich mal ganz stark.
Und auch an den Fragesteller die Aufforderung:
Bitte ersetzte solche vernünftige Namen nicht durch welche, die du dir 
gerade ausgedacht hast. Das ist nämlich auch beim Schreiben einer 
Antwort mehr als lästig, wenn man ständig rauf runter scrollen muss, nur 
um sich zu vergewissern ob man jetzt den richtigen Member genommen hat 
oder nicht. Mit einigermassen aussagekräftigen Variablennamen merkt man 
sich die leicht und selbst wenn man mal einen Tippfehler macht, ist das 
nicht so schlimm. Aber wenn das alles name1, name2, name5 test1, test2, 
test3, ... heißt, ist eine Verwechslung wahrscheinlich und auch nicht so 
leicht erkennbar.
Gast #2692986
Lesenswert?

OK. Ich habe einiges verstanden, bin mir aber nicht ganz sicher.
Ich habe mal ein einfaches beispiel konstruiert:

mein .c File:
1
typedef struct klassenkammeraden {
2
  char name;
3
  int alter;
4
  int mathenote;  
5
  int deutschnote;
6
  type durchschnittsnote; 
7
} tklassenkammeraden;
8

9
typedef void (*tklassenkammeraden) (const struct klassenkameraden *mathenote, char *deutschnote)

mein .c file:
1
extern const tParamDescription *Jens;
2
extern const tParamDescription *Achim;
3

4
const klassenkammeraden Jens =
5
{ Schmidt, 16, 3,  5, berechnedurchschnittsnote};
6

7
const klassenkammeraden Achim =
8
{ Maier, 17, 1,  3, berechnedurchschnittsnote};
9

10
int berechnedurchschnittsnote(const tklassenkammeraden *mathenote, char *deutschnote)
11
{
12
  int durschnitt = 0;
13
  durchschnitt = (( mathenote + deutschnote) /2)
14
}
15
  return durchschnitt;
16
  
17
 indieservarsolldiedurschnittsnotevonjensstehen = Jens->durchschnittsnote(mathenote,deutschnote);

ist das so richtig??
#2693029
Lesenswert?

Dein Beispiel ist reichlich sinnlos. Es bringt auch nichts, wenn du 
extrem lange Namen für ein Beispiel wählst. Wenn dir gar nichts anderes 
einfällt, dann benutze für ein Beispiel die Situation "Auto" oder 
"Haustiere". Das funktioniert meistens recht gut.


1
// Datentyp für den Funktionspointer erzeugen
2
sruct Hund;
3
tpydef void (*Aktion) (struct Hund* dog);
4

5
// Ein Hund hat einen Namen und als Funktionspointer verknuepft
6
// eine Funktion die aufgerufen werden kann, wenn der Hund jemanden
7
// begruessen soll
8
struct Hund
9
{
10
  char*  Name;
11
  Aktion Begruessung;
12
}
13

14
//
15
// Hier sind die möglichen Begruessungsaktionen. Jeweils als
16
// Funktion implementiert
17
//
18
void wedeln( struct Hund* dog )
19
{
20
  printf( "Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n", dog->Name );
21
}
22

23
void hochSpringen( struct Hund* dog )
24
{
25
  printf( "Hi, ich bin %s und zur Begruessung springe ich an dir hoch\n" dog->Name );
26
}
27

28
//
29
// Und dann gibt es noch 2 Hunde
30
// Sie haben jeweils unterschiedliche Namen und ihre Begruessungsaktionen
31
// sind verschiedene
32
//
33
struct Hund Fifi   = { "Fifi", wedeln };
34
struct Hund Brutus = { "Brutus", hochSpringen );
35

36

37
int main()
38
{
39
  // Beide Hunde sollen mal eine Begruessung machen
40

41
  // das kann jetzt so aussehen ...
42
  wedeln( &Fifi );
43
  hochSpringen( &Brutus );
44
  // .. aber dazu hat der Programmierer das Wissen benutzt, das
45
  // Fifi mit dem Schwanz wedelt und Brutus hochspringt. Diese
46
  // 'Verknuepfung' des Verhaltens ist an dieser Stelle direkt
47
  // im Programmcode enthalten.
48

49
  // genau das wollen wir aber manchmal nicht. Fifi soll selber
50
  // wissen, dass er mit dem Schwanz zu wedeln hat. Das weiß er auch.
51
  // Er weiß es in Form seines Funktionspointers, der zur Funktion
52
  // führt, die die Begruessung macht.
53
  // Also ....
54
  Fifi.Begruessung( &Fifi );
55
  Brutus.Begruessung( &Brutus );
56

57
  //
58
  // Soweit so gut. Interessant wird das ganze nämlich dann, wenn
59
  // im Code gar nicht mehr bekannt ist, um welchen Hund es sich
60
  // handelt.
61
  // Existiert nur ein Pointer auf irgendeinen Hund ....
62
  struct Hund* Koeter;
63

64
  // ... und zeigt dieser Pointer 'zufällig' auf Fifi ...
65
  Koeter = &Fifi;
66

67
  // ... dann wird ueber den Funktionspointer die jeweils
68
  // richtige Funktion ....
69
  Koeter->Begruessung( Koeter );
70

71
  // ... aufgerufen
72

73
  // und natuerlich auch, wenn dieser 'irgendein Hund' der andere
74
  // Hund ist.
75
  Koeter = &Brutus;
76
  Koeter->Begruessung( Koeter );
77

78
  // Man beachte: Der Funktionsaufruf ist in beiden Fällen syntaktisch
79
  // derselbe!
80
  // Koeter->Begruessung( Koeter );
81
  // und trotzdem wird je nachdem um welchen Hund es sich handelt, die
82
  // jeweils richtige Funktion aufgerufen. In der jeweiligen Objektinstanz
83
  // selber ist in Form eines Funktionspointers abgelegt, welche das ist.
84
  // Die Daten selber steuern die Programmausführung und nicht mehr
85
  // der Programmierer hat zur Entwicklungszeit festgelegt, welche Funktion
86
  // konkret aufzurufen ist.
87
  // D.h. er hat es schon festgelegt. So ein Programm kann ja auch nicht
88
  // zaubern. Aber er hat es hier
89
  //   struct Hund Fifi   = { "Fifi", wedeln };
90
  //   struct Hund Brutus = { "Brutus", hochSpringen );
91
  // an einer Stelle zentral festgelegt. Hier an dieser Stelle wurde
92
  // fuer jeden Hund seine Eigenschaften festgelegt. Nicht mehr quer
93
  // uber das Programm verstreut, sondern an einer Stelle zentral.
94
  //
95
  // Und wenn man diesen Gedanken weiterführt, noch ein paar Details ergänzt
96
  // dann führt dieser Gedankengang unmittelbar zu dem was man 'Objektorientierte
97
  // Programmierung" nennt.
98
}
Gast #2697179
Lesenswert?

Tatsächlich ist noch eine frage aufgekommen.

Was ich überhaupt nicht verstehe ist folgendes:
1
typedef struct Member {
2
  uchar name;
3
  uchar visits;  
4
} tMember;
5

6
extern const tMember membernumber;

Also wenn ich mehrere Member anlege, dtelle ich mir vor das für jeden 
Member Speicherplatz für den Namen und die Anzahl der Besuche festgelegt 
wird.
Was mach aber die Mitgliedsnummer? was ist der unterschied zu:

[c]
typedef struct Member {
  uchar name;
  uchar visits;
  int membernumber
} tMember;
Gast #2697191
Lesenswert?

membernumber ist eine Variable vom Typ tMember.

Mit
1
typedef struct Member {
2
  uchar name;
3
  uchar visits;  
4
} tMember;
wurde der Typ tMember definiert.
1
const tMember membernumber;
definiert eine Variable namens membernumber vom Typ tMember, also hat 
membernumber die Member name und visits.
Das Keyword extern besagt in dem Falle nur, dass membernumber in einer 
anderen Datei definiert wurde und in dieser Datei auch benutzt wird.
Gast #2697203
Lesenswert?

DAnke. Den namen muss ich dan wirklich noch ändern.
So habe die (vorerst) letzte Frage:
1
extern const tMember* const  list[];

hier wird ein array erzeugt, in dem alle Member stehen? Auch 
membernumber ? Kann ich tMember erzeugen die nicht in diesem array 
stehen?

Hups, jetzt sind es doch Fragen geworden.
#2697226
Lesenswert?

Jürgen schrieb:
> DAnke. Den namen muss ich dan wirklich noch ändern.
> So habe die (vorerst) letzte Frage:
>
>
1
> extern const tMember* const  list[];
2
>
>
> hier wird ein array erzeugt, in dem alle Member stehen?

Nein.
Lies die Deklaration. In diesem Array stehen keine Member, sondern in 
diesem Array sind Pointer enthalten, die auf Objekte vom Typ tMember 
zeigen können.

(Ich lass die const erst mal weg um dich nicht zu verwirren)
1
   
2
                 list         list ist
3
                 list[]       list ist ein Array
4
               * list[]       list ist ein Array von Pointern
5
       tMember * list[]       list ist ein Array von Pointern, wobei
6
                              jeder Pointer auf ein tMember zeigen kann
7
extern tMember * list[]       list ist ein Array von Pointern, wobei
8
                              jeder Pointer auf ein tMember zeigen kann
9
                              und dieses Array wird nicht hier erzeugt,
10
                              sondern existiert irgendwo anders im
11
                              Program

Immer schon mit der rechts/links Regel beim Variablennamen anfangen und 
sich nach aussen durcharbeiten.

> Auch
> membernumber ?

Wenn da irgendjemand mal die Adresse von membernumber ins Array eintägt 
dann steht der drinnen. Wenn nicht, dann nicht.
Technisch möglich ist es. Denn in list werden die Speicheradressen von 
tMember Objekten abgelegt. membernumber ist ein tMember Objekt. Also 
kann man seine Speicheradresse in diesem Array ablegen.

> Kann ich tMember erzeugen die nicht in diesem array
> stehen?

In dem Array sind überhaupt keine Member enthalten, sondern nur Pointer 
auf  tMember Objekte. Wo auch immer die erzeugt wurden und welcher Code 
auch immer diese ins Array eingetragen hat.

Analogie:
Dieses Array entspricht dem Schlagwortkatalog in einer Bibliothek. Die 
Bücher stehen irgendwo in den heiligen Hallen in einem Regal. IM Katalog 
gibt es für jedes Buch ein Kärtchen, auf dem steht: "Kernighan&Ritchi 
findet sich in Gang A, Regal 5, 6. Buch von links". Das ist das, was 
dein list Array machen kann: Einen Verweis zu geben, wo das tatsächliche 
Buch zu finden ist (und das du dir ausborgen solltest). Aber im 
Schlagwortkatalog sind NICHT die Bücher selber eingelagert.
Gast #2697295
Lesenswert?

Karl Heinz Buchegger schrieb:
> Du solltest den Hinweis im Bücherei-Beispiel ernst nehmen. Ich hab nicht
>
> ohne Grund dieses Buch ausgewählt.

Sorry, verstehe ich nicht.

Mir ist aber noch eine Ungereimtheit aufgefallen:

Laut http://c-buch.sommergut.de/Kapitel13/Strukturen.shtml ist ...
1
struct{
2
  char szName[30];
3
  char szVorname[30];
4
  unsigned long ulTel;
5
  unsigned long ulPlz;
6
  } Kunde, Lieferant;
7

8
////////////////////////////////////////////////
9
struct adresse{
10
  char szName[30];
11
  char szVorname[30];
12
  unsigned long ulTel;
13
  unsigned long ulPlz;
14
  };
15

16
struct adresse Kunde, Lieferant;
... das (annähernd) Selbe.

AVerr schrieb:
> Mittypedef struct Member {
>
>   uchar name;
>
>   uchar visits;
>
> } tMember;
>
>
>
> wurde der Typ tMember definiert.const tMember membernumber;
>
>
>
> definiert eine Variable namens membernumber vom Typ tMember, also hat
>
> membernumber die Member name und visits.
>
> Das Keyword extern besagt in dem Falle nur, dass membernumber in einer
>
> anderen Datei definiert wurde und in dieser Datei auch benutzt wird.

das passt aber hiermit nicht zusammen. oder?
#2697302
Lesenswert?

Jürgen schrieb:

> ... das (annähernd) Selbe.

Fast.
Das eine mal hat die Struktur einen Namen (und kann damit auch an 
anderen Stellen verwendet werden), das andere mal hat die Struktur 
keinen Namen. Da werden dann einfach 2 Variablen von diesem Typ erzeugt 
und das wars. Die STruktur kann abgesehen von diesen 2 Variablen 
nirgends anders mehr benutzt werden - weil sie ja keinen Namen hat mit 
dem man sie ansprechen könnte.

> das passt aber hiermit nicht zusammen. oder?

Das hat damit überhaupt nichts zu tun. Völlig andere Baustelle.


Bücherei:
Kernighan&Richtie
Programmieren in C
Gast #2697338
Lesenswert?

Jürgen schrieb:
> Wie völlig andere Baustelle? Das ist doch das Selbe, oder nicht?

Jürgen schrieb:
> Karl Heinz Buchegger schrieb:
>> Bücherei:
>> Kernighan&Richtie
>> Programmieren in C
> liegt hier neben mir

In dem Buch gibt es bestimmt einen Abschnitt über Structs und Typen ( 
Stichwort typedef ).

Ich kann mir schon denken, wo dein Problem liegt.
Wenn du so ein Struct siehst:
1
struct {
2
  int data;
3
} structVar
dann ist es auch richtig, dass structVar eine Variable ist, die diese 
Struktur erfüllt, du also auf das int structVar.data zugreifen kannst.
structVar hat in dem Fall einen konkreten Speicherbereich, in dem data 
gespeichert ist.

Im Falle
1
typedef struct {
2
  int data;
3
} tStruct;
ist tStruct nur der Name eines neuen Datentypen. Es bekommt keinen 
eigenen Speicher zugewiesen.
Du kannst nun aber Variablen dieses Typen erstellen, z.B. mit
1
tStruct structVar;
Diese structVar ist analog zu der oben, liegt im Speicher, du kannst 
structVar.data verändern.

Nun verstehst du hoffentlich auch, warum es eine komplett andere 
Baustelle ist ... aufgrund des Gebrauchs von typedef.
#2697353
Lesenswert?

Jürgen schrieb:
> Wie völlig andere Baustelle? Das ist doch das Selbe, oder nicht?

WAS ist dasselbe?
Bitte wirf mir nicht Satzfetzen vor und ich darf mir dann raussuchen, 
wovon du eigentlich sprichst.

Die einzige Gemeinsamkeit besteht darin, dass eine Struktur vereinbart 
wird. Das wars aber dann auch schon.
Jetzt kann ich mir aussuchen, ob sich deine Frage über die Gemeinsamkeit 
auf
* den Strukturnamen
* den typedef
* oder den extern
bezieht. Gottlob lautet in den letzten 2 Fällen die Antwort: andere 
Baustelle.
Gast #2699271
Lesenswert?

so ich habe versuch das hunde Beispiel zu compilieren um es besser zu 
verstehen.
Leider geht es nicht und ich verstehe nicht warum.

typedef und struct ist einmal falsch geschrieben.

Ich bekomme drei Fehlermeldungen:
1
void wedeln( struct Hund* dog )
two or more data types in declaration of wedeln
Syntax error before dog
1
 struct Hund Brutus = { "Brutus", hochSpringen );
syntax error before )

danke für eure Hilfe
Persönliche Seite #2699626
Lesenswert?

Martin G schrieb:
> Das macht ja gar keinen Sinn.

Doch, das hat sehr wohl einen Sinn, wir wollen hier schon wissen, mit 
welcher Instanz anonymer Benutzer wir es zu tun haben.

Andernfalls könnte ja auch jeder nicht angemeldete Benutzer von der 
Forensoftware als "Gast" bezeichnet werden ... dann haben wir viele 
Threads, in denen sich "Gast" mit "Gast" und "Gast" unterhält. Wenn dann 
noch "Gast", "Gast" und "Gast" dazukommen, wird es fast schon gemütlich.
Gast #2699649
Lesenswert?

Das habe ich nicht gemeint. Es macht aus meiner Sicht keinen Sinn. Es 
gibt ca 10M Jürgens in Deutschland. Wenn ich meine Identität verstecken 
wollte hätte ich mich einfach Jupp genannt.
Aber sei es wie es ist. Ich bin ich und versuche immer oben zu gucken 
wer "eingeloggt" ist, ich oder mein Bruder.

Ich habe versucht mein Problem zu lösen. Habe leider noch kein 
ergebniss. kann mir da jemand helfen?
Gast #2699985
Lesenswert?

So, selber probieren geht über studieren habe ich mit gedacht. Mein 
erstes Programm zum testen von Strukturen funktioniert:
1
struct hund 
2
       {
3
            char* name;
4
            int gewicht;
5
       };
6
       
7
struct hund Juergenshund   = { "Fifi", 15};
8
struct hund Sabineshund   = { "Ali", 11 };
9

10

11
int main ()
12
{
13
    while(1)
14
    {
15
            printf("%s wiegt %i \n", Juergenshund.name, Juergenshund.gewicht);
16
            printf("%s wiegt : %i \n", Sabineshund.name, Sabineshund.gewicht);        
17
    }  
18
}
Aber hier fangen schon die Probleme an. Das akzeptiert der compiler 
schon nicht:
1
struct hund 
2
       {
3
            char* name;
4
            int gewicht;
5
       }Michaelshund;
6
       
7
struct hund Juergenshund   = { "Fifi", 15};
8
struct hund Sabineshund   = { "Ali", 11 };
9

10
Michaelshund.name = "Bello";
11
Michaelshund.gewicht = 13;
12

13
int main ()
14
{
15
    while(1)
16
    {
17
            printf("%s wiegt %i \n", Juergenshund.name, Juergenshund.gewicht);
18
            printf("%s wiegt : %i \n", Sabineshund.name, Sabineshund.gewicht);
19
            printf("%s wiegt : %i \n", Michaelshund.name, Michaelshund.gewicht);        
20
    }  
21
}

und was auch nicht funktioniert ist:
1
typedef void (*Aktion) (struct hund* dog);
2

3
struct hund 
4
       {
5
            char* name;
6
            int gewicht;
7
            Aktion Begruessung;
8
       };
9
       
10
struct hund Juergenshund   = { "Fifi", 15, wedeln};
11
struct hund Sabineshund   = { "Ali", 11 , wedeln};
12

13
void wedeln( struct hund* dog )
14
{
15
  printf( "Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n", dog->Name );
16
}
17

18

19
int main ()
20
{
21
    while(1)
22
    {
23
            printf("%s wiegt %i \n", Juergenshund.name, Juergenshund.gewicht);
24
            printf("%s wiegt : %i \n", Sabineshund.name, Sabineshund.gewicht);        
25
    }  
26
}
Da wollte ich mal das mit den Funktionen testen. Wo liegen meine Fehler.
Persönliche Seite #2699996
Lesenswert?

> Aber hier fangen schon die Probleme an. Das akzeptiert der compiler
> schon nicht:
1
struct hund 
2
       {
3
            char* name;
4
            int gewicht;
5
       }Michaelshund;
6
       
7
struct hund Juergenshund   = { "Fifi", 15};
8
struct hund Sabineshund   = { "Ali", 11 };
9

10
Michaelshund.name = "Bello";
11
Michaelshund.gewicht = 13;

Die beiden Zuweisungen an die Strukturelemente von "Michaelshund" sind 
außerhalb einer Funktion nicht zulässig, im Gegensatz zu den 
Initialisierungen von Juergens- und Sabineshund.

> und was auch nicht funktioniert ist:
1
typedef void (*Aktion) (struct hund* dog);
2

3
struct hund 
4
       {
5
            char* name;
6
            int gewicht;
7
            Aktion Begruessung;
8
       };
9
       
10
struct hund Juergenshund   = { "Fifi", 15, wedeln};
11
struct hund Sabineshund   = { "Ali", 11 , wedeln};
12

13
void wedeln( struct hund* dog )
14
{
15
  printf( "Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n", dog->Name );
16
}

Zum Zeitpunkt der Initialisierung von Juergens- und Sabineshund ist die 
Funktion "wedeln" nicht bekannt. Du musst diese Funktion dem Compiler 
vor der Initialisierung bekanntmachen, entweder mit einem Prototypen 
(einer Deklaration) oder durch das Verschieben der Definition der 
Funktion vor die Initialisierungen.


Beides sind Dinge, die in einem anständigen C-Buch beschrieben werden. 
Den allfälligen Literaturhinweis will ich deswegen nicht weglassen:
Brian Kernighan & Dennis Ritchie, "Programmieren in C", 2. Ausgabe, 
Hanser-Verlag.

Aber auch die Fehlermeldungen des C-Compilers weisen auf diese 
Probleme hin, die gilt es zu lesen und zu verstehen.
Gast #2700066
Lesenswert?

das erste Problem ist gelöst. Danke.
Aber bei dem zweiten habe ich die Funktion verschoben, bekomme es aber 
immer noch nicht compeliert.
1
typedef void (*Aktion) (struct hund* dog); 
2

3
struct hund 
4
       {
5
            char* name;
6
            int gewicht;
7
            Aktion Begruessung;
8
       };
9
      
10
void wedeln( struct hund* dog )
11
{
12
  printf( "Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n", dog->Name );
13
}
14
       
15
struct hund Juergenshund   = { "Fifi", 15, wedeln};
16
struct hund Sabineshund   = { "Ali", 11 , wedeln};
17

18

19

20
int main ()
21
{
22
    while(1)
23
    {
24
            printf("%s wiegt %i \n", Juergenshund.name, Juergenshund.gewicht);
25
            printf("%s wiegt : %i \n", Sabineshund.name, Sabineshund.gewicht);        
26
    }  
27
}

Syntax error before Aktion
Gast #2700086
Lesenswert?

ich habe das buch ja gelesen; aber leider kann ich es nicht besser.

es geht um diese Zeile:
1
 Aktion Begruessung;

die Fehlermeldung ist komplet.
danachkommt noch eine Warning: no semicolon at end of struct
#2700095
Lesenswert?

Dann bekomme ich als Fehlermeldung:
t.cpp: In function ‘void wedeln(hund*)’:
t.cpp:15: error: ‘struct hund’ has no member named ‘Name’
t.cpp: At global scope:
t.cpp:18: warning: deprecated conversion from string constant to ‘char*’
t.cpp:19: warning: deprecated conversion from string constant to ‘char*’

(wenn ich es als C++ kompiliere) bzw.:

t.c:4: warning: ‘struct hund’ declared inside parameter list
t.c:4: warning: its scope is only this definition or declaration, which 
is probably not what you want
t.c: In function ‘wedeln’:
t.c:15: error: ‘struct hund’ has no member named ‘Name’
t.c: At top level:
t.c:18: warning: initialization from incompatible pointer type
t.c:19: warning: initialization from incompatible pointer type

als C.
#2700098
Lesenswert?

Martin G schrieb:
> so ich habe versuch das hunde Beispiel zu compilieren um es besser zu
> verstehen.
> Leider geht es nicht und ich verstehe nicht warum.

Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir 
dabei natürlich ein paar Tippfehler unterlaufen sind.

Für jemanden, der sein C zumindest soweit versteht, dass er sich in der 
Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein 
Problem sein.


> Ich bekomme drei Fehlermeldungen:
>
>
1
> void wedeln( struct Hund* dog )
2
>
> two or more data types in declaration of wedeln
> Syntax error before dog

Hier ....
1
// Ein Hund hat einen Namen und als Funktionspointer verknuepft
2
// eine Funktion die aufgerufen werden kann, wenn der Hund jemanden
3
// begruessen soll
4
struct Hund
5
{
6
  char*  Name;
7
  Aktion Begruessung;
8
}                <-------------------------------------------
9

10
//
11
// Hier sind die möglichen Begruessungsaktionen. Jeweils als
12
// Funktion implementiert
13
//

... fehlt ein ';'

Hier ....
>
1
>  struct Hund Brutus = { "Brutus", hochSpringen );
2
>
> syntax error before )
.... hab ich irrtümlich die falsche Klammer benutzt. ) anstelle von }
Gast #2700109
Lesenswert?

1
typedef void (*Aktion) (struct hund* dog); 
2

3
struct hund 
4
       {
5
            char* name;
6
            int gewicht;
7
            Aktion Begruessung;
8
       };
9
      
10
void wedeln( struct hund* dog )
11
{
12
  printf( "Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n", dog->name );
13
}
14
       
15
struct hund Juergenshund   = { "Fifi", 15, wedeln};
16
struct hund Sabineshund   = { "Ali", 11 , wedeln};
17

18

19

20
int main ()
21
{
22
    while(1)
23
    {
24
            printf("%s wiegt %i \n", Juergenshund.name, Juergenshund.gewicht);
25
            printf("%s wiegt : %i \n", Sabineshund.name, Sabineshund.gewicht);  
26
            wedeln( &Juergenshund );                 
27
    }  
28
}

So funktioniert es :-)
Mit den richtigen Fehlermeldungen kann man was anfangen. danke
Gast #2700112
Lesenswert?

Karl Heinz Buchegger schrieb:
> Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir
> dabei natürlich ein paar Tippfehler unterlaufen sind.
>
> Für jemanden, der sein C zumindest soweit versteht, dass er sich in der
> Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein
> Problem sein.

Nicht falsch verstehen. Ich bin dir ultra dankbar.
#2700119
Lesenswert?

Jürgen schrieb:
> Karl Heinz Buchegger schrieb:
>> Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir
>> dabei natürlich ein paar Tippfehler unterlaufen sind.
>>
>> Für jemanden, der sein C zumindest soweit versteht, dass er sich in der
>> Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein
>> Problem sein.
>
> Nicht falsch verstehen. Ich bin dir ultra dankbar.

OK. Dann war das wohl etwas zu subtil.
Nochmal Klartext: Du bist noch nicht soweit mit Funktionspointern 
rumzumachen. Mach deine Übungen in deinem Buch, arbeite die Kapitel 
durch, wenn dort Übungen angegeben sind, dann mach die, erfinde für dich 
Aufgaben. Lerne die Fehlermeldungen deines Compilers zu lesen. Lerne 
typische Fehlermeldungen und auch, dass sich die Meldung nicht unbedingt 
auf die gemeldete Zeile beziehen muss, sondern auch davor sein kann (und 
nur verschleppt wurde). Lerne wann das der Fall ist und auch wie es dazu 
kommt, dass ein Compiler beschwert, dass zb scheinbar eine Funktion 2 
Returntypen hat.
Und in ein paar Monaten bist du dann soweit, dass du dir den Kopf über 
Funktionspointer zerbrechen kannst.
Zu schnell vorzugehen bringt auch nichts. Ehrgeiz: ja. Aber falscher 
Ehrgeiz ist kontraproduktiv.

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