Forum: Compiler & IDEs Array übergeben


von riegaz (Gast)


Lesenswert?

Hallo, ich würde gerne ein Array mithilfe von Pointern aus der
"test.c" in die "main.c übergeben.
---- test.c --
uint8_t test(uint8_t id[],uint8_t *RET[])
{
  sp[0]=1;
  sp[1]=2;
  sp[2]=3;
  sp[3]=4;
  sp[4]=5;
  for (int i=0;i<5;i++){  *RET++ = sp[i];}
}
----
---- main.c --
int main(void
{
#include "test.h"

......
  uint8_t ret[5];
  test(&gSensorIDs[0][0][0],&ret);
  for (int i=0;i<5;i++){uart_puti(ret[i*2]);uart_puts_P("..");}
}
----
Mein Problem ist: Er schreibt in jedes zweite Feld ret[1],ret[3]...
eine "0" und ich verstehe nicht wieso. Mit ret[i*2] ist es zwar kein
Problem, aber trotzdem würd ich gern wissen woran es liegt!!!

Lg michi

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Daran, dass du das Kapitel über pointer & arrays im K&R nicht
verstanden hast.
1
uint8_t test(uint8_t id[],uint8_t *RET)
2
{
3
  sp[0]=1;
4
  sp[1]=2;
5
  sp[2]=3;
6
  sp[3]=4;
7
  sp[4]=5;
8
  for (int i=0;i<5;i++){  *RET++ = sp[i];}
9
}
10
...
11
int main(void
12
{
13
#include "test.h"
14
15
......
16
  uint8_t ret[5];
17
  test(&gSensorIDs[0][0][0],ret);
18
  for (int i=0;i<5;i++){uart_puti(ret[i]);uart_puts_P("..");}
19
}

Ich denke, dass "id" auch noch flasch ist, aber da fehlen die
Randinfos.

#include innerhalb einer Funktion ist normalerweise eher schlechter
Stil.

von Rolf Magnus (Gast)


Lesenswert?

for (int i=0;i<5;i++){uart_puti(ret[i*2]);uart_puts_P("..");}
}
----

> Mein Problem ist: Er schreibt in jedes zweite Feld
> ret[1],ret[3]...eine "0" und ich verstehe nicht wieso.

Eigentlich schreibst du in jedes zweite Feld gar nichts rein, d.h. es
steht nachher noch immer das drin, was zufällig vorher an dieser
Adresse stand. Nach dem Reset dürften das Nullen sein.

> Mit ret[i*2] ist es zwar kein Problem,

Doch, denn du hast ein Array aus 5 Elementen, also eines, auf das nur
mit Index 0 bis 4 zugegriffen werden darf. Dein Index geht aber bis 8.
Also schreibst du über das Ende des Arrays hinaus.

> aber trotzdem würd ich gern wissen woran es liegt!!!

Eben gerade an dem i*2. Wieso multiplizierst du überhaupt mit 2?

von Karl heinz B. (heinzi)


Lesenswert?

uint8_t test(uint8_t id[],uint8_t *RET[])
{
  ... *RET++ ...
}

Rhetorische Frage: was macht der ++
Um wieviel erhoeht er?

Nun da RET zuallererst mal ein Pointer auf Pointer ist,
erhoeht er um sizeof( uint8_t *).
Das moeschtest Du aber nicht, du moechtest um
sizeof( uint8_t ) erhoehen, da du ja an das naechste
Array Element ran kommen willst.
Da aber auf deinem System anscheinend
  sizeof( uint8_t*) == 2 * sizeof( uint8_t )
ist, beschreibst du nur jedes 2-te Array Element
(und hast einen klassischen Fall von: 'hinter ein
Array schreiben' und damit undefiniertes Verhalten)

Die Frage ist doch: Warum ueberhaupt dieser Mambo-Zambo
mit Pointer auf Array?
Du duerfte ein bekannter Denkfehler vorliegen: Arrays
werden naemlich sowieso immer per Pointer uebergeben.
Auch dann, wenn Du schreibst

  void foo( int A[] )

Das ist naemlich nichts anders als eine andere (unsaegliche)
Schreibweise fuer

  void foo( int * A )

oder in anderen Worten: Wenn einer Funktion ein Array
uebergeben wird, dann kann diese Funktion immer die
originalen Werte beim Aufrufer aendern. Das ist nun mal
so, Arrays verhalten sich hier anders als normale Variablen.
Andersrum ist es in C gar nicht moeglich: Es ist nicht moeglich
ein Array an eine Funktion zu uebergeben, sodass diese Funktion
eben nicht im originalen Array rumpfuschen kann.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

wenn man das aber will könnte man das Array in eine Struktur packen und
schon..... Lassen wir das sonst verwirren wir riegaz noch vollständig
:-)

Matthias

von riegaz (Gast)


Lesenswert?

ich bin schon verwirrt ;-)

sorry

von Marian (Gast)


Lesenswert?

Du bist nicht alleine :)...ich bin auch immmer verwirrt, wenn es um C
geht.

Gretz Marian

von Werner B. (Gast)


Lesenswert?

Der kleine Unterschied zwischen

<datentyp> array[<elements>];
 und
<datentype> pointer;

'array' ist der NAME einer Ansammlung von <datentyp> Elementen.
&array[5] kann zur Compilierzeit ausgewertet indem auf die Adresse des
ersten Elements 5 * sizeof(<datentype>) addiert wird.

'pointer' ist der Name einer VARIABLEN welche auf die Adresse einer
Ansammlung von <datentyp> Elementen zeigt.
&pointer[5] muss während des Programmablaufes ausgerechnet werden indem
der Inhalt der Variblen 'pointer' geladen wird und auf diesen Wert
(der zur Compilierzeit berechnete) Offset von 5 * sizeof(<datentype>)
addiert wird.

Der Wert von 'array' kann niemals verändert werden.
pointer = array; ist zulässig, array = pointer; aber nicht.

Im einem Programm steht also die Zeichenfolge 'array' für die Adresse
des Elements mit dem Offset 0 ( == &array[0] ), der Compiler 'ersetzt'
den Text 'array' durch eine Adresse.
Dagegen greift 'pointer' auf den eine Variable zu, der Compiler  Was
immer wieder verwirrt ist, dass man im Quelltext die gleichen
Operatoren verwenden kann.

von Christian Rötzer (Gast)


Lesenswert?

Letztlich will Dein Programm also wie folgt aussehen:

uint8_t test(uint8_t id[],uint8_t *RET)
{
  sp[0]=1;
  sp[1]=2;
  sp[2]=3;
  sp[3]=4;
  sp[4]=5;
  for (int i=0;i<5;i++)
  {
    *RET++ = sp[i];
  }
}
----
---- main.c --
#include "test.h"

int main(void)
{
......
  uint8_t ret[5];
  test(&gSensorIDs[0][0][0],ret);
  for (int i=0; i<5; i++)
  {
    uart_puti(ret[i]);
    uart_puts_P("..");}
  }
}

Es wurde eigentlich nur das [] im Kopf von Test entfernt, sowie beim
Aufruf der Adressoperator.
Wobei die Geschichte mit gSensorIDs weiterhin unheimlich aussieht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Siehe auch meinen zweiten Beitrag. ;-)

von Christian Rötzer (Gast)


Lesenswert?

Stimmt! Las' uns wieder über AVRDUDE diskutieren :-)

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.