array Zeigerarithmetik

#6943009
Lesenswert?

Hallo,

die Pointer bereiten mir etwas Probleme (.

Folgende Deklaration:
1
const __flash uint8_t (Data_init)[3][5]=
2
{
3
  {1,1,2,2,5};
4
  {2,2,2,2,5};
5
  {2,1,2,4,5};
6
};
7
uint8_t Data[5];
Nun sollen die Teilelemente einem neuen Array (1D) zugewiesen werden
1
for (i=0; i<3; i++){
2
    *Data= &Data_init[i][0];
3
    ....
4
}

Ich hatte es so verstanden, dass ein Zeiger auf das Element 0 dem 
Pointer auf das neue Array zugewiesen werden muss.
Klappt so aber nicht. Wo ist mein Gedankenfehler?
Persönliche Seite #6943013
Lesenswert?

Lars H. schrieb:
> const __flash uint8_t (Data_init)[3][5]=

Wozu die runden Klammern?

Lars H. schrieb:
> Ich hatte es so verstanden, dass ein Zeiger auf das Element 0 dem
> Pointer auf das neue Array zugewiesen werden muss.

Möchtest du Pointer übernehmen oder nur uint8_t-Zahlen? Dein 
"Data"-Array enthält einfach nur uint8_t Elemente. Die kannst du einfach 
direkt zuweisen:
1
for (i=0; i<3; i++){
2
    Data[i] = Data_init[i][0];
3
}

Das kopiert jeweils das 0. Element der Unter-Arrays nach Data. Keine 
Zeiger-Arithmetik, kein explizites Dereferenzieren oder Adressen nehmen. 
Data ist allerdings zu groß, die letzten beiden Elemente werden so nicht 
beschrieben. Oder was möchtest du erreichen?
#6943047
Lesenswert?

In C können keine Arrays mit = zugewiesen werden.
Dies geht nur mit integralen Typebn oder structs.

*Data ist mit Data[0] identisch.
(Der Compiler macht intern aus Data[i] ein *(Data+i) )

Daher bleibt dir nur die Schleife oder die Funktion memcpy (oder eine 
spezielle Anpassung für flash)
Persönliche Seite #6943050
Lesenswert?

Lars H. schrieb:
> jeweils 5
> uint8_t-Werte

Und warum zählst du dann bis 3?

Du möchtest also das innere Array kopieren. So kopierst du das 0. innere 
Array:
1
for (size_t i=0; i<5; ++i){
2
    Data[i] = Data_init[0][i];
3
}
Oder einfacher mit memcpy:
1
memcpy (Data, Data_init[0], sizeof(Data));

Oder wenn du doch was mit Zeigern machen möchtest, kannst du Data als 
Zeiger deklarieren und auf die Zeile zeigen lassen. Dadurch werden keine 
Daten kopiert, sondern Data verweist einfach auf das existierende 
Unter-Array:
1
const __flash uint8_t* Data;
2

3
Data = Data_init[0];

So kannst du aber natürlich die Inhalte nicht modifizieren, da keine 
Kopie im RAM angelegt wird.

Die Semikola in der Initialisierung von Data_init sind übrigens auch 
verkehrt...
#6943114
Lesenswert?

Hallo,

also noch mal kurz mein Verständnis:
-erster Index Zeilen, 2. Index Spalten
-da eine const im Flash nicht beschrieben werden kann, muss memcpy 
genommen werden
-
1
// 4 Zeilen 5 Spalten
2
int Matrix[4][5] = { {10,20,30,40,50},
3
                     {15,25,35,45,55},
4
                     {20,30,40,50,60},
5
                     {25,35,45,55,65}};
6
uint8_t Data[5];
7
memcpy (Data, Matrix[1], sizeof(Data))

Ergibt in Data:  15  0 25  0 35
sollte ergeben:  15 25 35 45 55
Offenbar wird zwischen 2 Elmenten immer eine 0 mit eingefügt- warum?

alternativ
1
int Matrix[4][5] = { {10,20,30,40,50},
2
                     {15,25,35,45,55},
3
                     {20,30,40,50,60},
4
                     {25,35,45,55,65}};
5
uint8_t* DataZ;
6
DataZ = Data_init[1];
ergibt nur einen Pointer, ich möchte aber die Werte ins neue Array 
übertragen (durch verschieben des Zeigers auf Zeile 1 von Matrix)

Wo ist mein Gedankenfehler?
Persönliche Seite #6943120
Lesenswert?

Lars H. schrieb:
> -erster Index Zeilen, 2. Index Spalten

Das ist nicht festgelegt, das kannst du auch anders herum 
interpretieren. Bei dieser Schreibweise stimmt es aber genau so:

Lars H. schrieb:
> int Matrix[4][5] = { {10,20,30,40,50},
>                      {15,25,35,45,55},
>                      {20,30,40,50,60},
>                      {25,35,45,55,65}};

Lars H. schrieb:
> Offenbar wird zwischen 2 Elmenten immer eine 0 mit eingefügt- warum?

Weil die Elemente der Matrix "int" sind, aber "Data" vom Typ uint8_t 
ist! memcpy prüft sowas nicht. Klassische Falle in C, und ist auch nicht 
wohldefiniert, d.h. am PC wäre das Ergebnis anders. Wenn du C++ 
verwendest kannst du das mit std::copy sauberer & sicherer machen:
1
std::copy (std::begin(Data_init[1]), std::end(Data_init[1]), std::begin(Data));

Wenn "Data_init" im Flash ist via __flash, geht memcpy wohl nicht. Wenn 
du statt __flash PROGMEM verwendest kannst du memcpy_P nehmen.
Persönliche Seite #6943132
Lesenswert?

Lars H. schrieb:
> -geht das mit einer const so überhaupt?

Ja, der Zeiger muss halt auch als "const" markiert werden, damit du 
darüber nicht versehentlich versuchst zu schreiben, also eben so:
1
const uint8_t* Data;
2
Data = Matrix[1];

> -wie müsste ich das genau machen, wenn Matrix kein const wäre?

Genauso, nur ohne const:
1
uint8_t* Data;
2
Data = Matrix[1];
#6943220
Lesenswert?

Lars H. schrieb:
> Wie ist es aber mit der 2. Variante, wo ich die Daten gar nicht
> "sinnlos" kopieren muss, sondern nur den Zeiger umsetze.
>
> -geht das mit einer const so überhaupt?

Ja.
const  char * Data; heißt "declare Data as pointer to const char"

Der Zeiger selber ist nicht const.

Soll der Zeiger const sein, wäre dass dann char * const  Data; "declare 
Data as const pointer to char"

Kann man auf https://cdecl.org ausprobieren (kennt nur kein stdint.h)

Das const schützt nicht vorm überschreiben.
Der Compiler kann anders optimieren und gibt Warnungen, wenn schreiben 
beim compilieren versucht wird.

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