Forum: Mikrocontroller und Digitale Elektronik Strukturenaufruf wie Funktion


von Jürgen (Gast)


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

von (prx) A. K. (prx)


Lesenswert?

"type" bzw. "name3" ist ein Zeiger auf eine Funktion. Und die wird exakt 
so aufgerufen.

von Yalu X. (yalu) (Moderator)


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.

von Jürgen (Gast)


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

von Rolf M. (rmagnus)


Lesenswert?

Jürgen schrieb:
> was verbirgt sich jetzt hinter name2 ?

Ein Zeiger auf eine Funktion.

> mit name4->name2(name4,name7);  schreibe ich in meine Instanz name4 an
> die Stelle name2 was?

Gar nichts. Du rufst die Funktion auf.

> Ich übergebe nur zwei Zeiger?

Ja.

von Karl H. (kbuchegg)


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.

von ... (Gast)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


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.

von Karl H. (kbuchegg)


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.

von Jürgen (Gast)


Lesenswert?

Das stimmt leider.
Da der Code nicht von mir ist, habe ich die richtigen Namen ersetzt. 
Beim nächsten mal werde ich mir bessere Namen ausdenken. :-)

von Jürgen (Gast)


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

von Jürgen (Gast)


Lesenswert?

oben das soll das header file sein (zumindest teile daraus) und nich das 
c file

von Jürgen (Gast)


Lesenswert?

Jürgen schrieb:
> extern const tParamDescription *Jens;
>
> extern const tParamDescription *Achim;

soll natürlich heißen:
1
 extern const tklassenkammeraden *Jens; 
2
 extern const tklassenkammeraden *Achim;

von Yalu X. (yalu) (Moderator)


Lesenswert?

Jürgen schrieb:
> ist das so richtig??

Nein, durch die erneute Namensänderungen ist jetzt fast alles falsch,
was man falsch machen kann.

Wenn du die Namen unbedingt ändern musst, mach es wenigstens mit
Search/Replace und schau, ob der Compiler das Ergebnis noch ohne
Fehlermeldungen und Warnungen annimmt.

von Jürgen (Gast)


Lesenswert?

ich habe das leider im Texteditor gemacht. da ich auf meinem Rechner 
keinen compiler installiert habe.

von Jürgen (Gast)


Lesenswert?

Yalu X. schrieb:
> Nein, durch die erneute Namensänderungen ist jetzt fast alles falsch,
>
> was man falsch machen kann.

das ist bitter, ich versuche mal die sachen runterzuladen.

von Karl H. (kbuchegg)


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
}

von Jürgen (Gast)


Lesenswert?

1000 Dank für eure Mühen. Ich analysiere das Programm mal und wenn noch 
fragen da sind, melde ich mich nochmal.

von Jürgen (Gast)


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;

von AVerr (Gast)


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.

von AVerr (Gast)


Lesenswert?

PS: membernumber ist ein ziemlich schlecht gewähler Name, da sich 
dahinter keine einfache Anzahl von Membern verbirgt.

von Jürgen (Gast)


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.

von Karl H. (kbuchegg)


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.

von Jürgen (Gast)


Lesenswert?

ICH SAG EUCH BESSER NICHT WAS ICH MIR VORGESTELLT HABE WAS DAS IST

von Karl H. (kbuchegg)


Lesenswert?

:-)
Ich kanns mir schon denken.

Du solltest den Hinweis im Bücherei-Beispiel ernst nehmen. Ich hab nicht 
ohne Grund dieses Buch ausgewählt.

von Jürgen (Gast)


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?

von Jürgen (Gast)


Lesenswert?

Jürgen schrieb:
> 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.

hat sich erledigt. Halbschlaf ;-)

von Karl H. (kbuchegg)


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

von Jürgen (Gast)


Lesenswert?

Wie völlig andere Baustelle? Das ist doch das Selbe, oder nicht?

von Jürgen (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Bücherei:
>
> Kernighan&Richtie
>
> Programmieren in C

liegt hier neben mir

von AVerr (Gast)


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.

von Karl H. (kbuchegg)


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.

von Martin G (Gast)


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

von Martin G (Gast)


Lesenswert?

schon wieder der schiss mit dem Namen. ich bin Jürgen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Martin G schrieb:
> schon wieder der schiss mit dem Namen. ich bin Jürgen.

Wir sind hier nicht besonders entzückt über Leute, die sich als mehrere 
unterschiedliche Leute ausgeben müssen.

Gewöhn' Dir das ab. Dringend.

von Martin G (Gast)


Lesenswert?

Das macht ja gar keinen Sinn. Das eine bin ich das andere mein Bruder. 
Ist doch eh anonym.
Sieht zwar doof aus, das gebe ich zu, aber ich bin ich :-) und mein 
bruder mein Bruder

von Jürgen (Gast)


Lesenswert?

so jetzt habe ich es :-)
Sorry

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Jürgen (Gast)


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?

von Jürgen (Gast)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Jürgen (Gast)


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

von Klaus W. (mfgkw)


Lesenswert?

Jürgen schrieb:
> Syntax error before Aktion

Das ist nicht die ganze Meldung.
Ich glaube zwar, in welcher Zeile das ist - aber es ist dein Job das zu 
sagen.

Sollen hier alle rumraten, nur weil du zu faul bist, eine vernünftige 
Fehlerbeschreibung zu machen?

von Klaus W. (mfgkw)


Lesenswert?

Abgesehen davon lässt du dir hier stückweise erzählen, was in jedem 
C-Buch steht.
Das ist nicht fein.

von Klaus W. (mfgkw)


Lesenswert?

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

Leg es doch mal vor dich, dann kannst du es lesen!

von Jürgen (Gast)


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

von Klaus W. (mfgkw)


Lesenswert?

Jürgen schrieb:
> es geht um diese Zeile:
>  Aktion Begruessung;

nein, oder dein Quelltext ist nicht komplett.
Bzw. sollte noch eine Fehlermeldung vorher kommen.

von Jürgen (Gast)


Lesenswert?

das einzige was noch vorher kommt ist :
1
#include <stdio.h>
2
#include <stdlib.h>

mehr ist wirklich nicht.

von Klaus W. (mfgkw)


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.

von Karl H. (kbuchegg)


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 }

von Jürgen (Gast)


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

von Jürgen (Gast)


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.

von Karl H. (kbuchegg)


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.

von Jürgen (Gast)


Lesenswert?

Das she ich ja ähnlich.
Leider bin ich beruflich gezwungen, den kram sofort zu verstehen. ich 
würde auch lieber langsam machen.

von Klaus W. (mfgkw)


Lesenswert?

Dann hast du zu spät damit angefangen :-)

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.