mikrocontroller.net

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


Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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



Autor: Jens (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste mal mehr und vor allen Dingen den tatsächlichen
Code.

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was ist denn

> idata myStruct tmp;

ich denke das sollte

myStruct tmp;

heißen

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ARM-Fan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ARM-Fan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mann soll es nicht glauben, aber folgendes funktioniert tatsächlich:
typedef struct
{
  unsigned char bla;
  unsigned char blubb;
} myStruct;

myStruct foo()
{
  myStruct temp;

  temp.bla = 1;
  temp.blubb = 2;

  return temp;
}

int main(void)
{
  myStruct result;

  result = foo();

  while(1);
}


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

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
myStruct functionName(void)
{
    //idata myStruct returnStruct;    //Deklariere Variable vom typ der
struct

   //mach was
   .
   .
   .

      returnStruct.super = 1;
      returnStruct.toll = 10;

      return returnStruct;
}

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.
void functionName( myStruct * dst )
{
    dst->super = 1;
    dst->toll = 10;
}

// Aufruf
myStruct tmp;
functionName( &tmp );


/*** oder ***/
myStruct * functionName( void ) 
{
    myStruct * returnStruct = new myStruct;
    returnStruct->super = 1;
    return returnStruct;
}

// Aufruf
myStruct * tmp;

tmp = functionName();
/* ... */
delete tmp;

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 
:)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.