Hallo,
die Pointer bereiten mir etwas Probleme (.
Folgende Deklaration:
1
const__flashuint8_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_tData[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?
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?
Runde Klammern können weg.
Ich möchte aus dem const-Array (__flash) wahlweise jeweils 5
uint8_t-Werte in mein Variablen-Array übernehmen, also immer eine ganze
Zeile (je 5 Elemente).
Damit sollte die Dimension eigentlich passen.
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)
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_ti=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__flashuint8_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...
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
intMatrix[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_tData[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
intMatrix[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?
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:
Lars H. schrieb:> Offenbar wird zwischen 2 Elmenten immer eine 0 mit eingefügt- warum?
Du kopierst ein int auf uint8_t.
Nimm die For Schleife und caste den int auf uint8_t (wenn dir bewusst
ist was bei negativen ints passiert).
Edit: zu langsam.
Ja stimmt, danke (dummer Fehler...)
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?
-wie müsste ich das genau machen, wenn Matrix kein const wäre?
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
constuint8_t*Data;
2
Data=Matrix[1];
> -wie müsste ich das genau machen, wenn Matrix kein const wäre?
Genauso, nur ohne const:
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.
Danke!
Ich habe gerade gemerkt, ich brauche in diesem Fall memcpy_P (wegen
_flash)
Allerdings ist das als Funktionsaufruf auch nicht effizient, gibt es das
auch inline?
Lars H. schrieb:> Allerdings ist das als Funktionsaufrauf auch nicht effizient, gibt es> das auch inline?
Der Compiler kann das falls sinnvoll automatisch inlinen. Um die paar
Takte muss man sich erstmal keine gesteigerten Sorgen machen...
Niklas G. schrieb:> Der Compiler kann das falls sinnvoll automatisch inlinen.
Das ist eine Assembler-Funktion, da wird der nicht allzu viel machen
können. Im Gegensatz zu memcpy hat der die _P-Version m.W. nicht
built-in.
Niklas G. schrieb:> Um die paar> Takte muss man sich erstmal keine gesteigerten Sorgen machen...
So ist es.
Oliver