Hallo an alle. Ich habe da ein Problem und hoffe, ihr könnt mir aus der Patsche helfen ;-) Also zuerst mal das Wichtigste: Ich verwende Keilµ Vision3 als C Compiler und arbeite auf einem 8051 Derivat. Nun habe ich folgendes Problem: Ich habe ein Hauptprojekt (enthält main.c) und ein zweites Keil Projekt, welches zu einer Library (.LIB) kompiliert und im Hauptprojekt eingebunden wird. Grundsätzlich funktioniert das einbinden der Lib und das aufrufen von enthaltenen Funktionen auch! Probleme gibt es bei eienr Funktion, die ein struct zurückliefern soll. Das struct ist global so definiert: typedef idata struct myStruct { unsigned char super; unsigned char toll; }myStruct; Die Lib sieht nun folgendermaßen aus: myStruct functionName(void) { //idata myStruct returnStruct; //Deklariere Variable vom typ der struct //mach was . . . returnStruct.super = 1; returnStruct.toll = 10; return returnStruct; } SO! Nun will ich im Hauptprogramm, wo die Funktion aufgerufen wird, den Rückgabewert(das struct) auswerten. Nachdem aber folgendes nicht geht(weiß nicht warum, bin ein C Anfänger): status = functionName().super; hab ich das so gemacht: //Deklariere eine Variable des selben struct in Hauptprogramm. idata myStruct tmp; //Schreibe Rückgabewert in tmp tmp = functionName(); Und nun kommts: Der Compiler meldet, dass der "=" Operator im Bezug auf diese Anweisung "inkompatible" ist. Ich frage mich warum,denn die Funktion liefert ein struct zurück und diese wil ich in eine Variable speichern, welche vom selben Typ ist?! Würde mich freuen, wenn jemand Licht in die Dunkelheit werfen könnte ;-) Danke! Grüße,Franz
Steig lieber um auf Assembler. Dann hast Du alles selber in der Hand :-))
was ist denn
> idata myStruct tmp;
ich denke das sollte
myStruct tmp;
heißen
Du hast 'idata' (wohl ein spezifischer 'Type qualifier' -- hab keine Ahnung von 8051ern) sowohl im typedef, als auch in den ganzen Deklarationen, das geht sicher schief. Aber ein anderes Thema: status = functionName().super; das sollte funktionieren, aber wozu gibt die Funktion ein struct zurück, wenn du nur einen Teil davon haben willst? hth. Jörg
Ok, alles der reihe nach! Danke auch alles für die Antworten. @Karl Heinz Buchegger: Hab nun leider nicht denb ganzen Code im Kopf, aber ich denke nicht, dass die anderen Anweisungen einen Einfluss auf mein Problem haben. @antworter: Das "idata" bedeutet im Prinzip nur, dass die angelegte Variable Im RAM des Controllers abgelegt wird. Eine andere Möglichkeit wäre "code" oder "data". @Jörg x: Also im Prinzip brauche ich schon beide Variablen (es werden noch ein paar hinzukommen), nur die restlichen benötige ich erst später im Code. Grüße, Franz
Also ich programmiere ja schon echt lange. Aber auf die Idee bzw. in die Verlegenheit, ein struct zurückgeben zu müssen, bin ich bisher noch nie gekommen. Ja, ich weiß noch nicht einmal ob das geht. Der Compiler bzw. der Controller müßte ja schließlich den Rückgabewert der Funktion - dein struct - in das Ziel-struct umkopieren. Ob er das tut kann ich mir gar nicht richtig vorstellen. Und warum brauchst du eine Kopie des structs aus der Funktion? Reicht es nicht einfach, wenn du die Referenz - also einen Zeiger - auf das struct zurückgibst? Die Funktion wird ja wie es aussieht ohne Parameter aufgerufen. Wass passiert denn darin so tolles, dessen Ergebnis ein struct ist?
Franz wrote: > @antworter: > > Das "idata" bedeutet im Prinzip nur, dass die angelegte Variable Im RAM > des Controllers abgelegt wird. Eine andere Möglichkeit wäre "code" oder > "data". Kleine frage, aber wo soll eine Variable sonst angelegt werden? Könnte höchstens noch im ROM sein, dafür gibts ja in der Regel auch modifier. Aber warum für den RAM? Sollte doch der Standardfall sein.
Naja also nicht unbedingt. Also genau genommen ist das ein etwas spezieller Controller, dessen Architektur nicht ganz die eines 8051ers entspricht. Eine variable kann nur im RAm liegen, oder aber auch im Flash (die Keil hilfe kann das besser erklären, ich hab nur das Programm leider nicht zu Hause ;-( ) Grüße, Franz
Sry, das mit RAM /Flash war vielleicht etwas dumm erklärt. Sagen wir so: Es gibt bestimmte Speicherbereiche im Controller, die sich unter anderem durch den Zugriff(also die Adressierung) unterscheiden und auch in der Art, wie eine Varibale/Funktion abgelegt wird... Aber um nicht vom eigentlichen Problem abzukommen. Auch ohne "idata" habe ich das selbe Problem!
Ist ein bischen undurchsichtig, vielleicht beschreibst du mal was du
eigentlich machen willst.
>> Poste mal mehr und vor allen Dingen den tatsächlichen Code.
Sehe ich auch so.
idata, indirekt addressierbarer RAM Bereich, er liegt parallel zu den
SFR's.
Mann soll es nicht glauben, aber folgendes funktioniert tatsächlich:
1 | typedef struct |
2 | {
|
3 | unsigned char bla; |
4 | unsigned char blubb; |
5 | } myStruct; |
6 | |
7 | myStruct foo() |
8 | {
|
9 | myStruct temp; |
10 | |
11 | temp.bla = 1; |
12 | temp.blubb = 2; |
13 | |
14 | return temp; |
15 | }
|
16 | |
17 | int main(void) |
18 | {
|
19 | myStruct result; |
20 | |
21 | result = foo(); |
22 | |
23 | while(1); |
24 | }
|
Allerdings nicht mitm C51 sondern MDK-ARM von Keil compiliert und durch den Simulator gejagt. Poste doch mal die genaue Fehlermeldung des Compilers / Linkers und laß uns nicht im dunkeln tappen. Und bevor wieder die Glaskugel- sprüche kommen... ;-)
1 | myStruct functionName(void) |
2 | {
|
3 | //idata myStruct returnStruct; //Deklariere Variable vom typ der
|
4 | struct
|
5 | |
6 | //mach was
|
7 | .
|
8 | .
|
9 | .
|
10 | |
11 | returnStruct.super = 1; |
12 | returnStruct.toll = 10; |
13 | |
14 | return returnStruct; |
15 | }
|
Nach ANSI C müsste das funktionieren. Ich würde allerdings auf call-by-reference bzw. Pointer umsteigen, da das Kopieren von Strukturen vermutlich viel Rechenzeit frisst.
1 | void functionName( myStruct * dst ) |
2 | {
|
3 | dst->super = 1; |
4 | dst->toll = 10; |
5 | }
|
6 | |
7 | // Aufruf
|
8 | myStruct tmp; |
9 | functionName( &tmp ); |
10 | |
11 | |
12 | /*** oder ***/
|
13 | myStruct * functionName( void ) |
14 | {
|
15 | myStruct * returnStruct = new myStruct; |
16 | returnStruct->super = 1; |
17 | return returnStruct; |
18 | }
|
19 | |
20 | // Aufruf
|
21 | myStruct * tmp; |
22 | |
23 | tmp = functionName(); |
24 | /* ... */
|
25 | delete tmp; |
Hey jungs! Echt spitze, eure Hilfe. Tut mir leid, dass ich euch ein wenig vertrösten muss, aber ich kann erst morgen die auf Wortlaut genaue Fehlermeldung des Compilers mitteilen, wie gesagt, hab Keil nicht auf meinem PC zuhause! Danke für die bisherig geleistete Hilfe, eure Beispiele allein helfen schon ein wenig weiter :-) Grüße, Franz
@ARM-Fan: Möglich, daß ich mich täusche, aber dein Beispielcode schaut mir in der vorliegenden Form nach einer bösen Falle aus ;) Weil: "myStruct temp" in der foo()-Funktion wird ja vermutlich am Stack angelegt. Die Funktion gibt dann die Adresse von temp zurück. Wenn das Resultat in der main gleich auswertest kein Problem, aber wenn du dazwischen was andres auf dem Stack machst steht in "myStruct result" nur mehr wirres Zeug (was eben grad an der Adresse im Stack steht ..). Schöne Grüße, Thomas
Thomas B. wrote: > @ARM-Fan: > > Möglich, daß ich mich täusche, aber dein Beispielcode schaut mir in der > vorliegenden Form nach einer bösen Falle aus ;) Du täuscht dich. Da geht alles mit rechten Dingen zu. > > Weil: > "myStruct temp" in der foo()-Funktion wird ja vermutlich am Stack > angelegt. Die Funktion gibt dann die Adresse von temp zurück. Genau das tut sie nicht. Sie gibt die Struktur zurück. Anders als bei Arrays können Strukturen tatsächlich als Objekte übergeben und auch retourniert werden. Bis jetzt ist in den Code-Beispielen nichts aufgetaucht, was für den Keil Compiler ein Verweigerungsgrund wäre. Deshalb auch die Frage nach mehr Code.
Ok, sorry für meinen Irrtum, hatte die Verwendung eines structs (bei C) so noch nicht gesehen. Arbeite da immer mit Adressen. Wieder was gelernt :)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.