Forum: Mikrocontroller und Digitale Elektronik C Code - Problem mit struct


von Franz (Gast)


Lesenswert?

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



von Jens (Gast)


Lesenswert?

Steig lieber um auf Assembler. Dann hast Du alles selber in der Hand 
:-))

von Karl H. (kbuchegg)


Lesenswert?

Poste mal mehr und vor allen Dingen den tatsächlichen
Code.

von antworter (Gast)


Lesenswert?

was ist denn

> idata myStruct tmp;

ich denke das sollte

myStruct tmp;

heißen

von Jörg X. (Gast)


Lesenswert?

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

von Franz (Gast)


Lesenswert?

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

von ARM-Fan (Gast)


Lesenswert?

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?

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Franz (Gast)


Lesenswert?

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

von Franz (Gast)


Lesenswert?

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!

von Joe (Gast)


Lesenswert?

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.

von ARM-Fan (Gast)


Lesenswert?

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... ;-)

von Florian (Gast)


Lesenswert?

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;

von Franz (Gast)


Lesenswert?

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

von Thomas B. (Gast)


Lesenswert?

@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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Thomas B. (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.