undefined reference to
-
Hallo an alle.
Zur Zeit sitze ich an einer Übungsaufgabe im c-howto Tutorial.
Darin geht es um eine Spielfigur, die in einem 8x8 Feld mit den Tasten a, w, d, s bewegt werden soll.
Für mich war die Aufgabe an manchen Stellen leider noch etwas zu kompliziert, so dass ich die entsprechenden Passagen abgetippt habe, um diese dann so nachzuvollziehen.#include<stdio.h> void printField(int *field); void move(int *field, int *posX, int *posY, char zug); int main() { int field[8][8] = {0}, posX=0, posY=0; char zug; //Setzen der Figur auf das Feld (0,0) field[posY][posX]=1; //Da posX und posY 0 sind, wird das Feld oben links mit 1 initialisert. printf("\nBeenden mit x\n"); do //Schleife erscheint immer nach dem Eintippen der Aufforderung. { printField(&field[0][0]); //Befehl, um das Feld auszugeben. printf("\nZuege: a links, w hoch, d rechts, s runter: "); scanf("%c", &zug); move(&field[0][0], &posX, &posY, zug); //Mit & wird der Zeiger aus der Funktion oben auf die Variablen gesetzt. } while (zug != 'x'); return 0; //Ausgabe Spielfeld void printField(int *field) { printf("\n"); int i, j; //Befehl für die Zeilen. Y-Achse for(i=0; i<8; i++) { //Befehl für die Spalten. X-Achse for(j=0; j<8; j++) { printf("%d ", *(field+i*8+j));//Insgesamt geht man von (0,0) aus i*8+j Felder weiter. } printf("\n"); } } //Bewegen der Spielfigur void move(int *field, int *posX, int *posY, char zug) { //Löschen der alten Position *(field + *posY*8 + *posX) = 0; /*Der Zeilenwert wird *8 gerechnet und dazu der Spaltenwert addiert. Durch das Initialisieren mit 0 wird die alten Position 'gelöscht' und die 1 durch eine 0 ersetzt. */ //Neue Position switch(zug) { case 'a': (*posX)--; break; case 'w': (*posY)--; break; case 'd': (*posX)++; break; case 's': (*posY)++; break; } //Überschreiten der Grenze if (*posX<0) *posX = 7; if (*posX>7) *posX = 0; if (*posY<0) *posY = 7; if (*posY>7) *posY = 0; //Neue Position bei Überschreitung *(field + *posY*8 + *posX) = 1; } }
Der Compiler meldet jetzt zwei Fehlermeldungen, nämlich
undefined reference to 'printField' und undefined reference to 'move'
Das beudeutet doch, dass der Compiler die Funktionen nicht mit den entsprechenden Verlinkungen im Hauptprogramm verbinden kann, oder?
-
Es gibt in C keine funktionslokalen Funktionen.
Alle Funktionen werden im Code global definiert
(Die Sichtbarkeit kann durchstatic
eingegrenzt werden)
-
Mit global ist gemeint, dass deine Funktionsdefinition außerhalb von main(){} liegen muss, also oberhalb oder unterhalb von main() und nicht wie bei dir innerhalb.
-
Hi
Danke für eure Antworten.
Dass die Funktionen außerhalb des Hauptprogrammes definiert werden müssen ist soweit verständlich.
Das Lustige ist jetzt aber, dass in der Musterlösung die Funktionen genau wie in meiner oben geposteten Lösung auch nicht vor dem Hauptprogramm definiert werden.
Und warum das dort dann trotzdem funktioniert verstehe ich nicht.#include<stdio.h> void printField(int *field); void move(int *field, int *posX, int *posY, char zug); int main() { int field[8][8] = { 0 }, posX=0, posY=0; char zug, temp; // setzen der Spielfigur field[posY][posX] = 1; printf("\nBeenden mit x\n"); do { printField(&field[0][0]); printf("\nZug [w hoch, a links, s runter, d rechts]: "); scanf("%c%c", &zug, &temp); move(&field[0][0], &posX, &posY, zug); }while(zug != 'x'); return 0; } // Ausgabe Spielfeld void printField(int *field) { printf("\n"); int i, j; // Schleife fuer Zeilen, Y-Achse for(i=0; i<8; i++) { // Schleife fuer Spalten, X-Achse for(j=0; j<8; j++) { printf("%d ", *(field+i*8+j)); } printf("\n"); } } // Spielfigur bewegen void move(int *field, int *posX, int *posY, char zug) { // alte Position loeschen *(field + *posY * 8 + *posX) = 0; // neue Position bestimmen switch(zug) { case 'w': (*posY)--; break; case 'a': (*posX)--; break; case 's': (*posY)++; break; case 'd': (*posX)++; break; } // Grenzueberschreitung pruefen if(*posX < 0) *posX = 7; if(*posX > 7) *posX = 0; if(*posY < 0) *posY = 7; if(*posY > 7) *posY = 0; // neue Position setzen *(field + *posY * 8 + *posX) = 1; }
-
Shelldor schrieb:
Das Lustige ist jetzt aber, dass in der Musterlösung die Funktionen genau wie in meiner oben geposteten Lösung auch nicht vor dem Hauptprogramm definiert werden.
Und warum das dort dann trotzdem funktioniert verstehe ich nicht.
...Schau dir mal ganz genau an welcher Stelle im Quelltext die geschweiften Klammern auf und zu stehen.
Dann solltest du den Unterschied zwischen den Quelltexten erkennen.
-
f.-th. schrieb:
Shelldor schrieb:
Das Lustige ist jetzt aber, dass in der Musterlösung die Funktionen genau wie in meiner oben geposteten Lösung auch nicht vor dem Hauptprogramm definiert werden.
Und warum das dort dann trotzdem funktioniert verstehe ich nicht.
...Schau dir mal ganz genau an welcher Stelle im Quelltext die geschweiften Klammern auf und zu stehen.
Dann solltest du den Unterschied zwischen den Quelltexten erkennen.Hmmm.... also ich erkenne, dass in beiden Quelltexten die geschweiften Klammern paarweise geöffnet und geschlossen sind. Es steht also keine Klammer 'alleine'.
Was mir auffällt ist, dass in der Musterlösung die geöffnete, geschweifte Klammern direkt nach der Funktionsverlinkung stehen. In meiner Lösung darunter.
Kann das etwas damit zutun haben?
-
In deiner Lösung ist
main
erst in Zeile 73 zu Ende.
Dadurch sind die anderen Funktionen innerhalb vonmain
. (Funktionslokal)In der Musterlösung ist
main
in Zeile 24 zu Ende.
Dadurch sind die anderen Funktionen global definiert.main
ist auch nur eine Funktion. Zwar mit spezieller Bedeutung und genormten Aufruf.
Sie wird als erste (User-)Funktion vom Startcode aufgerufen.Was verstehst du unter Funktionsverlinkung
-
er meint wahrscheinlich
void funktion(){ //code }
gegenüber
void funktion() { //code }
macht aber keinen unterschied, da man im prinzip auch
void funktion(){//code}
schreiben kann. klammern untereinander finde ich persönlich auch übersichtlicher und moderne entwicklungsumgebungen zeigen normalerweise das "gegenstück" zur jeweiligen klammer an, wenn man das caret neben diese bewegt.
-
DirkB schrieb:
In deiner Lösung ist
main
erst in Zeile 73 zu Ende.
Dadurch sind die anderen Funktionen innerhalb vonmain
. (Funktionslokal)In der Musterlösung ist
main
in Zeile 24 zu Ende.
Dadurch sind die anderen Funktionen global definiert.main
ist auch nur eine Funktion. Zwar mit spezieller Bedeutung und genormten Aufruf.
Sie wird als erste (User-)Funktion vom Startcode aufgerufen.Was verstehst du unter Funktionsverlinkung
Wahnsinn. Daran hat es gelegen
Vielen Dank!
Woran hast du das 'gesehen', dass dort der Fehler war?Mit 'Funktionsverlinkungen' meine ich das Ansprechen der Funktionen im Hauptprogramm.
HansKlaus schrieb:
er meint wahrscheinlich
void funktion(){ //code }
gegenüber
void funktion() { //code }
macht aber keinen unterschied, da man im prinzip auch
void funktion(){//code}
schreiben kann. klammern untereinander finde ich persönlich auch übersichtlicher und moderne entwicklungsumgebungen zeigen normalerweise das "gegenstück" zur jeweiligen klammer an, wenn man das caret neben diese bewegt.
Danke für die Antwort
War mir in dem Moment nicht so sicher, ob die Position der geschweiften Klammern Einfluss auf das Compilen haben.
Aber genauso meinte ich das
-
Shelldor schrieb:
Woran hast du das 'gesehen', dass dort der Fehler war?
Erfahrung.
Allerdings ist dein Code sehr schön eingerückt.
Darum kann man das sehr schön sehen.Auch die fehlende Klammer nach dem
return
inmain
, bzw. die folgende Funktionsdefinition und
die extra Klammer am Ende vom Code.