memcpy Zweidimensionales Array -> Eindimensionales Array

OP #2682691
Lesenswert?

Hi,

ich habe ein Problem mit memcpy und Array's un komme so nicht weiter.

Ich wollte folgende schreibweise (die funktioniert) vereinfachen:
1
struct ssetup
2
{  
3
  unsigned char nSensors;
4
  unsigned char tSensorsIDs[8][8];    
5
};
1
unsigned char tempID[8];
2
  
3
// erste ID ins RAM holen
4
tempID[0] = setup.tSensorsIDs[i][0];
5
tempID[1] = setup.tSensorsIDs[i][1];
6
tempID[2] = setup.tSensorsIDs[i][2];
7
tempID[3] = setup.tSensorsIDs[i][3];
8
tempID[4] = setup.tSensorsIDs[i][4];
9
tempID[5] = setup.tSensorsIDs[i][5];
10
tempID[6] = setup.tSensorsIDs[i][6];
11
tempID[7] = setup.tSensorsIDs[i][7];

Und hier mein Versuch mit memcopy der den unteren Programmteil ersetzen 
sollte. Klappt nur leider nicht:
1
unsigned char tempID[8];
2
  
3
// erste ID ins RAM holen
4
memcpy(tempID[0], setup.tSensorsIDs[i][0], sizeof(8));

Für eure Lösungsvorschläge wäre ich euch sehr dankbar.

Gruss Alois ;)
#2682692
Lesenswert?

Alois Neumann schrieb:
> Klappt nur leider nicht:

tja, die übliche aussagekräftige Fehlerbeschreibung...

Vielleicht klappt es so besser:
1
// erste ID ins RAM holen
2
memcpy( &tempID[0], &setup.tSensorsIDs[i][0], 8*sizeof(setup.tSensorsIDs[i][0]));

An memcpy müssen 2 Adressen übergeben werden (wohin? woher?), nicht die 
Werte der Feldelemente - daher die &.

sizeof(8) ist auch ziemlich sinnlos, weil es dir die Größe einer int 
liefert (die Speichergröße der Zahl 8, sizeof(42) wäre gleichwertig).
Stattdessen willstu doch 8*(ein Feldelement) kopieren - deshalb 
8*sizeof(setup.tSensorsIDs[i][0]). Ebensogut würde 8*sizeof(unsigned 
char) funktionieren.
OP #2682697
Lesenswert?

Klaus, erstmal vielen Dank für die schnelle Hilfe.

Deine Version funktioniert. Das mit den Pointern hatte ich auch schon 
probiert. Der Knackpunkt war die Übergabe der Grösse.

Was ich immer noch nicht verstehe. tempID[8] ist doch 8Bytes gross, 
oder?
Werden jetzt mit memcpy nur 8 Bytes kopiert, oder 64Bytes?

Gruss Alois
#2682699
Lesenswert?

Alois Neumann schrieb:
> Deine Version funktioniert. Das mit den Pointern hatte ich auch schon
> probiert.

Die Version von user ist ebenso korrekt.

Alois Neumann schrieb:
> Was ich immer noch nicht verstehe. tempID[8] ist doch 8Bytes gross,
> oder?
> Werden jetzt mit memcpy nur 8 Bytes kopiert, oder 64Bytes?

tempID[8] kann zweierlei sein...

1.
1
unsigned char  tempID[8];

definiert ein Feld mit 8 Elementen.

2.
Nachdem das Feld schon existiert, ist tempID[8] ein Element, nämlich das 
achte nach Feldbeginn (und damit das erste hinter dem Feld):
1
   tempID[8] = 42; // falsch, da hinter Feld!
Hier ist ein Element des Feldes gemeint, wenn auch ein verbotenes, da 
nur [0] bis [7] im Feld liegen.
sizeof(tempID[8]) ist die Größe eines solchen Elements, also 1 (weil ein 
Feldelement vom Typ unsigned char ist und damit 1 Byte groß).

Bei sizeof ist es nicht schädlich, wenn man ein Element außerhalb des 
Feldes angibt statt innnerhalb. Schließlich geht es nur um die Größe 
eines Objekts im Speichers, also um seinen Typ. Wirklich darauf 
zugegriffen wird bei sizeof nicht.

Also: sizeof(tempID[8]) ist hier 1, sizeof(tempID) und 
8*sizeof(tempID[8]) wären 8.
Gast #2684079
Lesenswert?

Hallo Forum,
ich bekomme die Warnmeldung:
"..warning: implicit declaration of function 'memcpy'
..warning: incompatible implicit declaration of built-in function 
'memcpy'"

obwohl das Programm funktioniert. Die Meldung wird beim kopieren vom 
eindimensionalen Array in das zweidimensionale Array geworfen.
Wo liegt mein Fehler???

Deklaration:
1
char DisplayBuf[2][16]; // the Display Buffer
2
char TransferBuf[16]; // the Transfer Buffer

hier tritt die Warnung auf:
1
memcpy(&DisplayBuf[i], &TransferBuf, sizeof(TransferBuf));

Transfer Buffer wird gefüllt:
1
sprintf(TransferBuf, "Menu %2d, %2d, %2d", StartPos, CoursorPos, Test->ID);

Danke vorab für Eure Hilfe.
Gast #2684197
Lesenswert?

Hallo Klaus,

kapern wollte ich den Thread nicht, ich dachte das es zum Thema passt.
Gleiche Klasse? Nein, nicht das ich das wüßte.

memcpy wird in der Standard "string.h" deklariert:
1
extern void *memcpy(void *, const void *, size_t);
...und das war auch gleich das Problem, ich dachte eher an die 
pgmspace.h - war aber ein Lesefehler.

Danke trotzdem.
#2684232
Lesenswert?

Daniel Held schrieb:

> memcpy wird in der Standard "string.h" deklariert:
>
1
> extern void *memcpy(void *, const void *, size_t);
2
>
> ...und das war auch gleich das Problem, ich dachte eher an die
> pgmspace.h - war aber ein Lesefehler.

Also ich hätt da ja eher an memory.h gedacht.

string.h      alle str... Funktionen zur Manipulation von Strings
memory.h      alle mem... Funktionen zur Manipulation von Bytefeldern
pgmspace.h    alle pgm... Funktionen zur Manipulation vom Flash


(und ja. memcpy kommt auch in string.h vor)
#2684242
Lesenswert?

Alle String- und mem*-Funktionen sind im C-Standard m.W. in string.h.
Daß das je nach Implementation in einer memory.h stehen kann und die von 
string.h #includet wird, kann sein. Aber string.h ist die korrekte 
Datei, wenn man memcpy nehmen will.
(HAbe eben auf meinem Linux nachgesehen: dort includet memory.h die 
string.h...)
Die pgmspace-Dinger sind ja eh kein Standard.

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