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