C Code - Problem mit struct

Gast #587220
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


Gast #587241
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
Gast #587256
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
Gast #587259
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?
Persönliche Seite #587260
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.
Gast #587267
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
Gast #587269
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!
Gast #587281
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.
Gast #587288
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... ;-)
Gast #587298
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;
Gast #587313
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
Gast #587415
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
#587433
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren