Forum: Mikrocontroller und Digitale Elektronik Funktionszeiger und Struktur Problem


von Simon (Gast)


Lesenswert?

Hallo zusammen,

Ich weis dass ich jetzt warscheinlich "Prügel" bekomme aber um ne 
konstruktive Antwort wäre ich trotzdem dankbar weil ich  komme einfach 
nicht weiter....


Ich will mit nem Atmega8 und nem LCD Display ein Menü programmieren.

Habe mir dazu aus dem FAQ Artikel mit den Funktionszeigern und dem 
Beitrag:
Beitrag "Menü Programmierung"

den Quellcode herausokopiert und dieser lässt sich nun nicht 
compillieren...
Habe ich vllt. ein #include vergessen o.ä???

Hier der Code:
1
struct MenuEntry//[] =  //Anlegen der Struktur Menü
2
  {
3
    char Text[20];
4
    MenuFcnt Funktion;  
5
  };
6
  
7
  struct MenuEntry MainMenu[5] =
8
  {
9
    { "ltonh", cleangetonl},
10
    { "ltonl", cleangetonh},
11
    { "frql",  cfreqtonl},
12
   {"frqh", cfreqtonh},
13
   {"test",help}
14
  };


Das ganze soll den "Pieper" an meinem AVR ansteuern und Frequenz und 
Tonlänge der Variablen verändern.

Die Funktionen habe ich bereits geschrieben und die Funktionieren 
einzeln soweit. Es läuft momentan auch alles über Globale Variablen denn 
Funktionen haben auch keinen Rückgabewert..

achso btw Compiler ist AVR Studio 4.


Vielen Dank im Voraus.

Simon

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

> den Quellcode herausokopiert und dieser lässt sich nun nicht
> compillieren...


Dann solltest du als erstes mal die Fehlermeldung lesen bzw. hier 
verraten. Die wird ja nicht ohne Grund ausgegeben und der Compiler gibt 
ja auch nicht ohne Grund nicht einfach nur "Fehler" von sich sondern 
einen Hinweis, was denn nicht passt. Manchmal sind diese Hinweise 
schlecht verständlich und man muss um ein paar Ecken denken, aber im 
Grunde ist der Fehlertext immer der Schlüssel.

von Georg G. (df2au)


Lesenswert?

Simon schrieb:
> struct MenuEntry//[] =  //Anlegen der Struktur Menü
>   {
>     char Text[20];
>     MenuFcnt Funktion;
>   };

Ohne Kenntnis des gesamten Programms geraten:

Ich hätte "MenuFcnt *Funktion;" geschrieben. Wobei dann davor gestanden 
hätte
"typedef void MenuFcnt(void)".

Wenn du Platz im RAM sparen willst, solltest du die Strings ins Flash 
verfrachten.

von Karl H. (kbuchegg)


Lesenswert?

Georg G. schrieb:
> Simon schrieb:
>> struct MenuEntry//[] =  //Anlegen der Struktur Menü
>>   {
>>     char Text[20];
>>     MenuFcnt Funktion;
>>   };
>
> Ohne Kenntnis des gesamten Programms geraten:
>
> Ich hätte "MenuFcnt *Funktion;" geschrieben. Wobei dann davor gestanden
> hätte
> "typedef void MenuFcnt(void)".

Ich tippe ja sowieso auf: Er hat den typedef komplett vergessen.

Aber hier gehts auch um mehr. Eine Anfrage "der COmpiler will nicht" ist 
hier im Forum nun mal sinnlos. Wir sehen den Code nicht, wir sehen den 
Compiler-Output nicht, wir haben nur das, was der Fragesteller postet. 
Und das muss so vollständig sein, dass man damit was anfangen kann.
Und das muss er lernen.

von Matthias L. (Gast)


Lesenswert?

>Wir sehen den Code nicht, wir sehen den Compiler-Output nicht...

... und somit muss der Fehler in Zeile 42, Spalte 42 liegen.

von Simon (Gast)


Lesenswert?

So habe mir das ganze nochmals angeschaut:

Fakt ist ich verstehe die Ausgabe des Compilers  nicht...
Der Rest vom Quellcode sind nur meine selbstgeschriebenen Funktionen.
Die ich für den Test auskommentiert habe. Alle Funktionen sind ohne 
Rückgabewert.

Unten findet ihr auch alle meine #include's


1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include "lcd-routines.h"
4
#include "lcd-routines.c" //muss zwingend die .c mit eingebunden werden?
5
#include <string.h>
6
#include <stdlib.h>
7
#include <stdio.h>
8
9
10
11
  typedef void(*MenuFnct)(void);
12
 
13
  struct MenuEntry //[] =  //mit und ohne = das gleiche Ergebnis...
14
  {
15
    char Text[20];
16
/*LN213*/  MenuFcnt Funktion;  
17
  };
18
  
19
  struct MenuEntry MainMenu[5] =
20
  {
21
   //{ "ltonh", cleangetonl},
22
    //{ "ltonl", cleangetonh},
23
    //{ "frql",  cfreqtonl},
24
   //{  "frqh", cfreqtonh},
25
/*LN222*/ {"test",help}
26
  };



Compiler Ausgabe:

../Piep2.c:213: error: expected specifier-qualifier-list before 
'MenuFcnt'
../Piep2.c:222: warning: excess elements in struct initializer
../Piep2.c:222: warning: (near initialization for 'MainMenu[0]')



Grüße

Simon

von Simon (Gast)


Lesenswert?

Noch ne kleine Ergänzung:

Hatte vorher das ganze in einer Funktion ausgeführt nun habe ich es 
nochmals in der main probiert da bekomme ich folgende Ausgabe:

../Piep2.c:243: error: expected identifier or '(' before '[' token
../Piep2.c:249: error: array type has incomplete element type

1
  typedef void(*MenuFnct)(void); 
2
  /*LN243*/struct MenuEntry [] =  //Anlegen der Struktur Menü
3
  {
4
    char Text[20];
5
    MenuFcnt Function;  
6
  };
7
  
8
/*LN249*/struct MenuEntry MainMenu[] =
9
  {
10
   // { "ltonh", cleangetonl},
11
    //{ "ltonl", cleangetonh},
12
    //{ "frql",  cfreqtonl},
13
   //{  "frqh", cfreqtonh},
14
   {"test",help}

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

>   typedef void(*MenuFnct)(void);

lies mal genau.
Wie heißt der neue Datentyp?
...Fnct  oder  ...Fcnt?  (Reihenfolge vom c und n)

>   struct MenuEntry //[] =  //mit und ohne = das gleiche Ergebnis...
>   {
>     char Text[20];
> /*LN213*/  MenuFcnt Funktion;

und was hast du hier geschrieben?



Das Fnct steht für 'Function'. Erst 'n', dann 'c'

von Simon (Gast)


Lesenswert?

AAARRRGHHHHHHH!!!!! diletantenklatsche


Vielen Dank!

den Schreibfehler habe ich nicht gesehen.... habe aber dafür 3 Abende 
lang gesucht......

schönen Feiertag....

Gruß
Simon

von Matthias L. (Gast)


Lesenswert?

>habe aber dafür 3 Abende lang gesucht......

..und du hast was gelernt. Das wird nicht so schnell wieder passieren 
;-)

von Karl H. (kbuchegg)


Lesenswert?

Und ich gebe durchaus zu, dass die Fehlermeldung des Compilers hier 
verwirrend bzw. irreführend ist. Im Nachhinein versteht man sie aber und 
auch wie es dazu gekommen ist.

Als sich der Compielr das hier
1
  struct MenuEntry
2
  {
3
    char Text[20];
4
    MenuFcnt Function;  
5
  };

vorgenommen hat, ist er auf MenuFcnt gestossen. An dieser Stelle kann 
das nur der Beginn einer neuen Memberdeklaration sein. Die sieht aber 
immer nach dem Muster aus (etwas vereinfacht)
1
    Datentyp   Name_des_Members  eventuelle_Array_Angabe ';'

d.h. nach dem ; in der Zeile davor muss die Angabe eines Datentyps 
stehen. Also hat der Compiler durchsucht, ob er MenuFcnt irgendwo 
findet. Eingebauter Datentyp (char, int, double, ...) ist es nicht. Das 
Schlüsselwort 'struct' oder 'union' ist es auch nicht. Was ist mit 
typedef-Aliases? Auch nicht - es gibt keinen dieses Namens.

Daher hat der Compilerbauer entschieden, dass man an dieser Stelle wohl 
den Datentyp vergessen hat. So wie in
1
struct xxx
2
{
3
  a;
4
  b;
5
};

Also beschwert er sich, dass da was fehlt:

../Piep2.c:213: error: expected specifier-qualifier-list before
'MenuFcnt'

Er hätte also erwartet, dass hier erst mal die Spezifizierung des 
Datentyps kommt, statt dessen kam aber der Name des Members. So dachte 
er zumindest. Er hat angenommen, dass du einen Strukturmember mit Namen 
'MenuFcnt' vereinbaren möchtest. Was ja auch ok ist. Nur braucht der 
dann eben einen Datentyp.


Tippfehler dieser Art können zu den abenteuerlichsten Fehlermeldungen 
führen, weil der Compiler dann alles mögliche 'verwechselt'. Ist halt 
auch nur eine Maschine, die nach starren Regeln vorgeht.
Aber mit der Zeit wird es besser. Dann kennt man für die meisten der auf 
den ersten Blick seltsamen Fehlermeldungen ein paar typische 
Fehlerszenarien und klappert den Source Code einfach danach ab.

PS: vergessene ';' nach einer struct Definition führen auch zu den 
abenteuerlichsten Fehlermeldung
1
struct xyz
2
{
3
  int a;
4
  int b;
5
}
6
7
void foo()
8
{
9
}

Die Fehlermeldung wird sich im Dunstkreis des void bei der Funktion 
bewegen. Der Compiler wird die Strukturdefinition erst mal als den 
Rückgabedatentyp der Funktion auffassen. Und da kommt ihm dann das void 
in die Quere, denn eine Funktion kann nur 1 Datentyp für die Rückgabe 
haben.

Sowas
1
struct xyz { int a; int b; } foo()
2
{
3
}
ist in C nämlich legal. Gemeinsam mit der Funktion wird auch die 
Struktur definiert, die das Aussehen des Rückgabewertes regelt. Und mit 
dieser Absicht verwechselt der Compiler das Obige. Dabei fehlt nur ein 
';' nach der struct-Definition. Besonders hinterhältig ist das Ganze 
genau dann, wenn die struct-Definition in einem eigenen Header File 
steckt, so dass man sie nicht gleich sieht

header.h
1
struct xyz
2
{
3
  int a;
4
  int b;
5
}

main.c
1
#include "header.h"
2
3
void foo()
4
{
5
  ...
6
}

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.