Das liegt an der automatischen Prototyp Erzeugung der IDE. Wenn du structs als Parameter verwendest, erstellt die IDE einen Funktions-Prototyp und schreibt diesen ganz oben hin. Wo das struct nicht bekannt ist. Die Lösung ist den Prototyp einfach per Hand zu erstellen.
Wobei sonst noch zwei Sachen nicht passen:
1.) Komplexe Datentypen wie structs übergibt man als Referenz! Sonst wird eine Kopie erstellt
2.) Deine Funktion hat einen Rückgabewert, aber gibt nichts zurück
Punkt 2 lässt sich auch einfach umgehen wenn du Punkt 1 umsetzt. Dann sind Änderungen in der Funktion sowieso nach außen sichtbar
Ich schließe mich mal Serenifly an und frage zusätzlich: Welche IDE verwendest du??? In Versionen unter 1.6.9 kommt es in der Tat zu den o.g. Fehlern inkl. Abbrüchen; in der Version 1.6.9 wird das Programm zwar kompiliert, wirft aber eine Menge Warnungen heraus, die die Aussagen von Serenifly unterstützen.
Letztens wurde mal der Prototyp-Parser verbessert. Aber ob er inzwischen mit struct-Parametern umgehen kann weiß ich nicht. Ist möglich wenn es in einer neueren Version ohne Fehler kompiliert. Aber die Warnung sollte man aktivieren und beachten! Das mit dem Rückgabe-Wert produziert zwar keine Fehler, aber manche Warnung wie diese sind praktisch schon Fehler.
Folgende Fehlermeldungen bekomme ich:
struct_test_03:6: error: variable or field 'testcode' declared void
struct_test_03:6: error: 'Daten1' was not declared in this scope
struct_test_03:6: error: 'testzahlen' was not declared in this scope
variable or field 'testcode' declared void
Wo liegt denn nun der Hund begraben?
Das einzige was ich wissentlich gegenüber #3 geändert habe ist, dass die Variablen global statt lokal in setup() deklariert sind.
Bei mir geht es. Ist aber 1.6.9. Wobei es da auch ohne Prototyp geht Dann scheint diese Änderung in 1.6.7 doch was gebracht zu haben:
New arduino-builder: faster, better prototype generation
Früher ging das ohne korrekten Prototyp nie
Genaugenommen sollte es aber so sein:
void testcode (Daten1& testzahlen);
Weiß nicht ob der Parameter-Name einen Unterschied macht. Manchmal wird er auch ganz weggelassen (was wieder mal historisch aus den C-Urzeiten kommt).
Aber bei dir könnte er da jetzt durcheinander kommen weil du plötzlich einen Namen angibst der schon für ein Objekt vergeben ist
Es ist übrigens auch nicht toll ein struct als Parameter zu übergeben und es dann in ein globales zu kopieren. Am konsequentesten wäre es beide als Parameter zu übergeben (nach dem üblichen Ziel/Quelle Prinzip). Am einfachsten wäre statt dessen memcpy() zu verwenden. Dann geht es ganz ohne eine eigene Funktion
peter_de:
n/muss ich machen dass diese fehlerfrei übersetzt wird?
Was soll das Programm denn machen, wenn es fehlerfrei übersetzt wird?
Das Programm enthält so offensichtliche und schwerwiegende Fehler, dass es nicht nur nicht fehlerfrei compiliert werden kann, sondern dass ich nicht mal erkennen kann, was das Programm machen soll.
Üblicherweise dienen dazu Kommentare im Quelltext.
Erster Rateversuch: Soll das eine Übung werden mit dem Thema "wie man mit wenigen Zeilen Code möglichst viel Quatsch programmiert"?
Ich mache noch einen zweiten Rateversuch;
Möchtest Du den Inhalt einer struct-Variablen in eine andere struct-Variable hineinkopieren?
Es ist übrigens auch nicht toll ein struct als Parameter zu übergeben und es dann in ein globales zu kopieren.
Ich wollte es gerade auch schon schreiben; irgendwie ist das nämlich in meinen Augen Unfug, der sich von hinten durch die Brust ins Auge schießt. Wenn ich schon irgendwelche Variablen oder Structs "global" definiere, kann ich auch direkt "global" damit arbeiten - ohne das Gehampel mit Funktions-Parameter etc. So im Sinne von:
Man sollte aber auch mal lernen wie man das ohne globale Variablen macht. Es kommt z.B. auch oft vor dass man eine Funktion braucht die ein struct als Parameter hat das dann von irgendwo mit Daten befüllt wird, z.B. Werte von einem Sensor oder der Inhalt einer Datei von einer SD Karte.
Hallo,
und Entschuldigung dass ich hier etwas Verwirrung gestiftet habe.
Ich glaube ich muss zur Klarstellung etwas weiter ausholen.
Mein eigentlicher Sketch geht über 11 Tabs und belegt ca.95kB im Programmspeicher eines MEGA2560.
Ich glaube den will hier niemand sehen sonst wird die Verwirrung noch größer.
Das Programm wird mit der IDE 1.6.5 fehlerfrei übersetzt und läuft auch problemlos.
In einem dieser 11 Tabs sind mehrere struct-Variablen definiert. Diesen Tab wollte ich eliminieren indem ich diese Variablen an der Stelle deklariere an der auch alle anderen globalen Variablen deklariert sind.
Um das Problem vereinfacht darzustellen habe ich im Eingangspost versucht einen Beispielcode (ohne sittlichen Nährwert) zu zeigen der das eigentliche Problem kurz und bündig beschreibt. Das hat jetzt leider auch zu den memcpy() Lösungen geführt. Sorry deswegen. memcpy() passt im realen Sketch nicht. Dort geht es nicht darum eine struct-Variable in eine andere zu kopieren.
Ich glaube irgendwo mal gelesen zu haben, dass man struct-Variablen, wenn sie mal deklariert sind, im Programm so verwenden kann wie int oder float ect. Das funktioniert in der Arduino-IDE dann scheinbar doch nicht so wie gedacht und verhält sich bei verschiedenen IDE-Versionen wohl auch noch unterschiedlich.
Ich will halt einfach nur diesen (lästigen) Tab mit den struct-Variablen, der im "Hauptprogramm.ino" includiert wird los werden.
Diese struct-Variablen werden zum Teil als Parameter an Funktionen übergeben zum Teil greifen aber auch andere Funktionen auf die global deklariert Variablen direkt zu. Darum auch die globale Deklaration der struct-Variablen im Eingangspost.
Ich bin halt auch nicht der große Programmiermeister und deshalb entstehen manchmal solche "unseriösen" Konstruktionen, zum Teil (wie auch in diesem Fall) durch copy&paste von irgendwo gefundenem fertigem Code.
Ich glaube ich lasse den Tab mit den struct-Variablen einfach weiterhin bestehen, denn eine einfache Lösung, wie ich dachte, die mit allen IDE-Versionen harmoniert scheint es nicht zu geben.
So wird mein Beispiel in Version 1.6.9 fehlerfrei übersetzt und mit meiner 1.6.5 läuft es auch nicht wenn ich Funktionsprototypen anlege.
Mit den in einen Tab ausgelagerten struct-Variablen klappte es schon mit der IDE 1.0.6, der 1.5.x und jetzt auch mit der 1.6.5.
Das Problem im Zusammenhang mit Funktionen ist wie gesagt in erster Linie die automatische Prototyp Generierung. Wenn die IDE Funktions-Prototypen generiert, werden (oder wurden?) die ganz oben hingeschrieben wo das struct noch nicht deklariert wurde. Dann beschwert sich der Compiler natürlich dass er das nicht kennt. Wenn man den Prototypen per Hand hinschreibt umgeht man das.
Bei Tabs ändert sich vielleicht die Reihenfolge in der das vor dem Compilieren zusammenkopiert wird.
Richtig .cpp und .h Dateien zu verwenden statt einfach nur .ino Tabs würde auch helfen. Auch daran denken dass Tabs in alphabetischer Reihenfolge abgearbeitet werden! Es ist also u.U. möglich in einem Tab etwas verwenden zu wollen, dass da noch noch nicht bekannt ist. Das kann man auch umgehen wenn man die Datei für die globalen Variablen z.B. "aGlobal.ino" nennt (sofern nicht doch noch was anderes davor kommt)
An dem was Tommy56 geschrieben hat ist auch was dran. Das struct keyword sollte an der Stelle eigentlich nur in C nötig sein und nicht in C++ (die Sprachen unterscheiden sich da), aber ich hatte glaube ich auch schon ein paar Fälle wo es solche Probleme gelöst hat.
Ich habe den Vorschlag von Tommy56 auch ausprobiert. Das hat aber ebenfalls nichts gebracht.
Dann habe ich das Programm das mit der IDE1.6.5 lauffähig übersetzt wird mit der Version 1.6.9 und 1.6.11 übersetzt. Das Ergebnis ist, dass ich bei beiden Versionen vom Fehlermeldungen erschlagen werde.
Meine Erkenntnis daraus ist, dass ich einen besch... Programmierstil habe und den grundlegend ändern muss um künftig mit den neueren IDE-Version lauffähige Programme zu erhalten.
Damit ich jetzt nicht auch noch zusätzlich mit Fehlern in der IDE kämpfen muss eine Frage an die Allgemeinheit. Welche IDE von .cc ist nach der 1.6.5 die empfehlenswerte weil "fehlerfrei" ?
Meine Erkenntnis daraus ist, dass ich einen besch... Programmierstil habe und den grundlegend ändern muss um künftig mit den neueren IDE-Version lauffähige Programme zu erhalten.
Hört sich gruselig an, dass muss ich sagen, und ein Kern Wahrheit steckt da auch drin.
Auch wenn es dir nicht direkt weiter hilft:
Wissen + Disziplin = gutes Programm
Danke @combie für die aufmunternden Worte.
Wissen muss ich noch zusammentragen, bei der Disziplin gebe ich mir Mühe.
Ich versuche gerade Code aus der "alten" Version in der IDE 1.6.11 neu zu gestalten.
Dazu habe ich verschiedene Tabs angelegt um etwas Struktur in die Sache zu bringen.
U.A. gibt es die Tabs "Setup.cpp", "Setup.h", "LCD.cpp" und "LCD.h".
In "LCD.cpp" stehen weitere Ausgaben auf das Display. Z.B:lcd.setCursor(0, 2);Dazu gibt es dann aber die Fehlermeldung: error: 'lcd' was not declared in this scope
Das kann ich soweit auch verstehen weil das Objekt? lcd in "LCD.cpp" nicht bekannt ist.
Wie muss ich das handhaben. Wie kann ich lcd in "LCD.cpp", oder besser global, bekannt machen?