Forum: Compiler & IDEs struct übergeben füllen und wieder zurück.


von Oddel (Gast)


Lesenswert?

morsche,

ich kapiers nicht ! Ich habe 2 .C Files.
In dem einen habe ich meine main() Funktion und die Deklaration einer 
Struct , alla :
1
File1.c:
2
3
typedef struct { unsigned char Daten[10]; }Data;
4
5
6
int main(void){
7
    ....
8
    Data myData;
9
    machwas(&myData); // übergibt doch Referenz auf Data oder nicht ?
10
    ....
11
}
12
13
14
File2.c:
15
16
void machwas(Data *daten){
17
     daten[1]=100;
18
    
19
  return *daten;
20
}

da fängts schon direkt an,dass er Data nicht kennt, ok wird ja nur im 
File1 deklariert. Ich kann jetzt zwar die Deklaration im File2 noch 
einmal machen, macht aber doch keinen Sinn oder ?

Ich will "nur" eine definierte Struct an eine Funktion übergeben, füllen 
lassen und wieder zurück damit. Sollte eigentlich nicht so schwer 
sein...

gruß
Oddel

von Frickler (Gast)


Lesenswert?

Zwei Fehler in drei Zeilen Code.

Du kannst keinen Wert zurückgeben, wenn Du die Funktion als void 
deklarierst

Wenn Du einen Pointer auf eine Struct übergibst, musst Du den Pointer 
natürlich auch dereferenzieren:
1
void machwas(Data *daten)
2
{
3
    daten->Daten[1] = 100;
4
}

von Albert .. (albert-k)


Lesenswert?

Du hast den Zugriff auf Elemente eines Structs nicht verstanden. 
Außerdem deklarierst du deine Funktion mit dem Rückgabewert void, hast 
aber ein return drinne? Auch falsch.

Dein Aufruf müsste wie folgt aussehen
1
File2.c:
2
3
void machwas(Data *daten){
4
     daten->Daten[1]=100;
5
}
Um es dir vl. etwas verständlicher zu amchen mal eine etwas klarere 
Namensgebung
1
File2.c:
2
3
void machwas(Data *GivenStruct){
4
     GivenStruct->Daten[1]=100;
5
}

von Michael H. (michael_h45)


Lesenswert?

Was für einen Sinn soll eine Struktur mit nur einem Element haben?
Sicher musst du die Variable auch in der zweiten c-Datei deklarieren - 
und zwar als "extern".

Außerdem brauchst du auch kein typedef in deinem c-File.
1
struct blabla_typ
2
{
3
  unsigned short vara;
4
  int varb, varc;
5
};
6
[c]
7
dann ein mal:
8
[c]struct blabla_typ blabla_tag;

und alle anderen male:
1
extern struct blabla_typ blabla_tag;

benutzung:
1
void foobar()
2
{
3
  blabla_tag.vara = 1337;
4
  blabla_tag.varb = -128;
5
}

Vorsicht falls du bei der Deklaration auch gleich initialisiert: 
Initialisierung bei der externen Deklaration weglassen!

von Oliver (Gast)


Lesenswert?

Oddel schrieb:
> Ich kann jetzt zwar die Deklaration im File2 noch
> einmal machen, macht aber doch keinen Sinn oder ?

Doch. Genauso geht es, und nur so. Um sich die Tipparbeit zu ersparen, 
schreibt man die Deklaration daher üblicheriwese in ein headerfile, 
welches dann von allen .c-Dateien, die dieses Struct benutzen, 
inkludiert wird.

Oliver

von Header (Gast)


Lesenswert?

Oddel schrieb:
> ok wird ja nur im
> File1 deklariert. Ich kann jetzt zwar die Deklaration im File2 noch
> einmal machen, macht aber doch keinen Sinn oder ?

Dafür gibt es header files mit Endung .h. Die bindest du mit #include in 
beide c files ein.

struct macht so verwendet keinen Sinn. Ist das zum üben, oder kommen 
weitere Daten hinzu?

von Oddel (Gast)


Lesenswert?

upps, das ging ja schnell. Danke !
ok das mit dem void da gehört mir eins hinter die Ohren.
Grundsätzlich wollte ich ein Array als Rückgabewert einer Funktion und 
habe dann im Galileo online book, den Umweg über die Struct gefunden. 
Hat aber nicht funktioniert und jetzt habe ich soviel probiert.....
Wie macht ihr die Rückgabe eines Arrays ?

von DirkB (Gast)


Lesenswert?

Oddel schrieb:
> Grundsätzlich wollte ich ein Array als Rückgabewert einer Funktion

Warum? Da du die Referenz auf das Array übergibst (den Zeiger), kannst 
du in dem Array doch eh alles ändern was du willst.

Kauf dir ein anderes Buch (von einem anderem Autor).

von Michael H. (michael_h45)


Lesenswert?

Oddel schrieb:
> habe dann im Galileo online book, den Umweg über die Struct gefunden.
Übler Mist, der nicht andres macht, als die Optimierung herauszufordern.

Den Zeiger kriegst du bei deinem Array eh frei Haus - der optimale 
Übergabewert.

von Guru (Gast)


Lesenswert?

@ Oddel

>... habe dann im Galileo online book, den Umweg über die Struct gefunden.

Möglicherweise lohnt es sich, wenn Du uns mal den Link auf die 
HTML-Seite in der Online-Version gibst, auf der steht, das man Daten 
innerhalb einer struct an eine Funktion übergibt, um sie dauerhaft 
manipulieren zu können.
Ich vermute, dass es sich um ein Missverständnis handelt, das man mit 
Gewinn für Dich aufklären könnte. Oder es handelt sich um einen echten 
Fehler in dem Buch, worüber man den Verlag aufklären könnte.

Es ist wohlgemerkt nicht unmöglich das so zu tun aber völlig unnötig.

von Oddel (Gast)


Lesenswert?

ah ok,

das bedeutet , das hier wäre absolut korrekt, ich übergebe die Referenz 
data , fülle die Speicheradresse mit Daten und das war's keine Rückgabe 
nix, da der Speicher direkt verändert wird.




[c]
int main(void){

  unsigned char data[10];

  machwas(&data);

  ....
}


file2.c

void machwas(unsigned char *daten){
   int i =0;
   for(i=0;i<= Packetlen ;i++){
       daten[i]=holeDaten();
     }

}


ok, wenn jetzt daten[], Datenpakete enthält mit 10 Byte länge und ich 
die Anforderung zum füllen der daten[] über einen Interrupt bekomme, 
würde es doch Sinn machen aus diesem Array ein 2 Dimensionales Array zu 
machen oder ein Struct - Array ?
Bsp.:

INT -> hole Datenbyte 1...10 und schreibe in Array daten !
mitten in der Verarbeitung von diesem Array kommt erneut ein
INT -> hole Datenbyte 1...10 und schreibe in nächstes Array daten !
usw.

Gruß
Oddel

P.S.: Tolles Forum !

von DirkB (Gast)


Lesenswert?

Oddel schrieb:
> machwas(&data);

ist so nicht richtig.

entweder
 machwas(&data[0]);
oder besser
1
 machwas(data);

Da machwas() aber nicht weiß und auch nicht raus finden kann wie groß 
der Platz in data ist, solltest du ihn mit übergeben.
Bedenke das bei dir das Element data[10] nicht existiert.

Auch ist es in C üblich einen Funktionswert zurück zu geben. Sei es als 
Fehlererkennung oder zur Weiterverarbeitung. Du musst ihn ja nicht 
beachten.
1
unsigned char * machwas(unsigned char *daten, int anz){
2
   int i =0;
3
   for(i=0;i< anz ;i++){
4
       daten[i]=holeDaten();
5
     }
6
   return daten
7
}

von Michael H. (michael_h45)


Lesenswert?

Hier mal ein Stück code von mir, in dem genau sowas gemacht wird.
uarx[] ist global und enthält empfangene Daten.
*command ist ein pointer auf ein array. Aufgerufen wird das so:
1
if( chk_for_cmd("set-blabla") )  do_blabla();
1
unsigned char chk_for_cmd(const char *command)
2
{  /* !WILDCARD character! == '#' will be passed to uarx_param */
3
  volatile unsigned char *uarxp=&uarx[0];
4
5
  if(uarx_done)
6
  {  /* uart rx done - process receivings */
7
    while(*uarxp == *command)
8
    {  /* if current characters are identical, *
9
        * increase to check next character     */
10
      uarxp++;
11
      command++;
12
      if(*command=='#')
13
      {  /* wildcard character for numbers */
14
        uarx_param=*uarxp;
15
        uarxp++;
16
        command++;
17
      }
18
      if(*command=='\0')
19
      {  /* next character to compare matches string-end *
20
          * -> whole command-string detected -> return 1 */
21
        uarx_done=0;
22
        uarx_clr();
23
        return 1;
24
      }
25
    }
26
  }
27
  /* no return 1 -> command not detected -> return 0 */
28
  return 0;
29
}

Die Variante mit dem lokalen array verbraucht nur mehr Speicher, weil er 
einmal im Unterprogramm und einmal beim Aufrufenden belegt werden muss.

von Oddel (Gast)


Lesenswert?

Hallo DirkB,

Danke für Dein Beispiel hat funktioniert ! Endlich mal wieder Licht am 
Ende des Tunnels :)

Aber eine Frage habe ich noch:
ich rufe die Funktion
1
machwas(daten); 
2
3
unsigned char * machwas(unsigned char *daten, int anz){
4
   int i =0;
5
   for(i=0;i< anz ;i++){
6
       daten[i]=holeDaten();
7
     }
8
   return daten
9
}

auf. Diese hat doch ein Return-Statement , wieso bringt mir der Compiler 
einen Fehler wenn ich aus machwas(daten);  ->   Dummy=machwas(daten) 
mache ?

gruß
Oddel

von DirkB (Gast)


Lesenswert?

Fehlermeldung wäre hilfreich.

Von welchem Typ ist Dummy?

von Oddel (Gast)


Lesenswert?

Dummy von unsigned char:

main.c|200|error: void value not ignored as it ought to be|

kann ich ein Array das ich mit &data übergebe und in der Funktion mit 
*data verarbeite an eine weitere Funktion mit data übergeben ?
Also von main -> Func1 und dann -> Func2 ?
Und kann ich mit
Arrsize = (Data,sizeof(Data) / sizeof(Data[0]))

die Anzahl Elemente ermitteln ?

und wofür genau steht * am Funktionsnamen in Deinem Beispiel ?

Danke , ich glaub das waren genug Fragen für heute.....

von DirkB (Gast)


Lesenswert?

Oddel schrieb:
> und wofür genau steht * am Funktionsnamen in Deinem Beispiel ?

Das besagt, das die Funktion einen Zeiger zurückgibt. Genauer einen Wert 
vom Typ (unsigned char *).

Die Anzahl der Elemente geht mit
1
Arrsize = (sizeof(Data) / sizeof(Data[0]) )

ACHTUNG. Das geht aber nur da, wo das Array auch bekannt ist.
In der Funktion machwas() geht das nicht mehr.

Und klar kannst du die Daten weiterreichen.

Zu der Fehlermeldug: Irgendwo hast du machwas noch mit void als 
Rückgabewert definiert.

von Oddel (Gast)


Lesenswert?

Hallo Dirk,

vielen Dank für Deine Hilfe. Bis jetzt macht mein Programm gute 
Fortschritte.
Wie kann ich ein Array zur Manipulation an einen Interrupt übergeben 
bzw.
von einem Interrupt auf die Speicherstelle zugreifen ?

Ich deklariere das Array im File1.c und verarbeite den Interrupt in 
File2.c....


gruß

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.