memcpy(), welchen Wert sollte der Größenparameter haben?

Lesezeit: 1 Minute

Benutzer-Avatar
Thomas

Ich möchte eine kopieren int Array zu einem anderen int Reihe. Sie verwenden dieselbe Definition für die Länge, sodass sie immer dieselbe Länge haben.

Was sind die Vor-/Nachteile der folgenden zwei Alternativen des Größenparameters zu memcpy()?

memcpy(dst, src, ARRAY_LENGTH*sizeof(int));

oder

memcpy(dst, src, sizeof(dst));

Wird die zweite Option immer funktionieren? Unabhängig vom Inhalt?

Eine Sache, die letzteres begünstigt, ist, dass, wenn sich das Array ändert, es einige Haushaltsführung sein wird, um das zu aktualisieren memcpy()‘s.

  • Es hängt ganz davon ab, wie Sie deklariert haben dst (und in gewissem Umfang, ob oder nicht src ist gleich oder größer als dst).

    – Traumlax

    21. April 2010 um 7:44 Uhr


Benutzer-Avatar
Timbo

So lange wie dst wird als Array mit einer Größe deklariert, sizeof gibt die Größe dieses Arrays in Bytes zurück:

int dst[ARRAY_LENGTH];

memcpy( dst, src, sizeof(dst) ); // Good, sizeof(dst) returns sizeof(int) * ARRAY_LENGTH

Wenn dst nur zufällig ein Zeiger auf das erste Element eines solchen Arrays ist (das den gleichen Typ wie das Array selbst hat), funktioniert es nicht:

int buffer[ARRAY_LENGTH];
int* dst = &buffer[0];

memcpy( dst, src, sizeof(dst) ); // Bad, sizeof(dst) returns sizeof(int*)

Benutzer-Avatar
Gregor Pakosz

sizeof(dst) ist nur richtig, wenn dst ist ein Array, dessen Größe zur Kompilierzeit bekannt ist: like int arr[ARRAY_LENGTH] oder ein C99-Array mit variabler Länge; Andernfalls wird die Größe eines Zeigers zurückgegeben, nicht die Länge des Zielarrays.

Um zukünftige Fehler zu vermeiden, seien Sie konsequent und bevorzugen Sie die erste Form: Typgröße * Länge.

  • Wirklich? Ich habe int arr[10]; cout << sizeof(arr) << endl; um 40 zu bekommen, was ich vermute, ist nicht der Zeigerwert.

    – Thomas

    21. April 2010 um 7:38 Uhr

  • Ah ja, es liegt daran, dass es statisch zugewiesen ist

    – Gregory Pakosz

    21. April 2010 um 7:39 Uhr

  • Die Antwort ist immer noch nicht richtig, weil in C99 sizeof gibt die Größe eines Arrays variabler Länge zurück, die (normalerweise) nur zur Laufzeit bekannt ist.

    – Traumlax

    21. April 2010 um 7:41 Uhr

  • dreamlax > Ich habe es der Antwort hinzugefügt

    – Gregory Pakosz

    21. April 2010 um 7:44 Uhr

  • wenn es als int dst deklariert ist[10] sizeof(dst) gibt die Größe des Arrays zurück

    – mkamthan

    21. April 2010 um 7:44 Uhr

Benutzer-Avatar
David Rodríguez – Dribeas

Wenn und wann Sie ein Array (echtes) haben, können Sie das verwenden sizeof(array) Beachten Sie jedoch, dass Sie, wenn Sie den Code umgestalten und an eine Stelle verschieben, an der das Array in einen Zeiger zerfallen ist (oder wenn der Speicher ursprünglich in einem Zeiger (malloc/new) zugewiesen wurde), eine bekannte Größe übergeben müssen.

Wenn Sie die relativen Größen von Quelle und Ziel ignorieren, das heißt, vorausgesetzt, dass sie für den Rest der Diskussion gleich sind, würde ich Ihnen bei Verwendung von C++ einen Metaprogrammierungstrick empfehlen, der Ihnen eine typsichere Größenzählung für Arrays gibt und dies nicht tun wird kompilieren, wenn Sie versuchen, es mit Zeigern zu verwenden:

template <typename T, int N>
inline int array_memory_size( T (&a)[N] ) { return sizeof a; }

Dieser Weg:

int main() {
   int array[10];
   int *ptr = array;
   int orig[10] = { 0 };
   memcpy( array, orig, array_memory_size(array) ); // ok
   //memcpy( ptr, orig, array_memory_size(ptr) ); // compilation error
}

Wenn Sie zu irgendeinem Zeitpunkt umgestalten und der Code an eine Stelle verschoben wird, an der das Array verfallen ist (oder Sie ein statisches Array durch ein dynamisch zugewiesenes ersetzen), teilt Ihnen der Compiler mit, dass Sie die Größenberechnung korrigieren müssen.

  • Ich habe nicht einmal bemerkt, dass die Frage markiert war c+++1!

    – Traumlax

    21. April 2010 um 7:51 Uhr

  • sehr schön, aber eben return sizeof a; reicht.

    – Ben Voigt

    18. Oktober 2013 um 0:53 Uhr

Benutzer-Avatar
Scott Wales

Wenn Sie mit malloc zugewiesen haben, müssen Sie die Größe des Arrays angeben

int * src = malloc(ARRAY_LENGTH*sizeof(*src));
int * dst1 = malloc(ARRAY_LENGTH*sizeof(*dst1));
memcpy(dst1,src,ARRAY_LENGTH*sizeof(*dst1));

Wenn Sie mit einem statischen Array zugewiesen haben, können Sie einfach verwenden sizeof

int dst2[ARRAY_LENGTH];
memcpy(dst2,src,sizeof(dst2));

Wird die zweite Option immer funktionieren? Unabhängig vom Inhalt?

Die 2. Option funktioniert nur, wenn Sie die fehlenden hinzugefügt haben ) und dst ist ein statisches Array (also vom Typ int[123]).

Wenn dst hat eine unbekannte Größe (z int[]), dann sizeof dst gibt nur die Zeigergröße zurück, da dst ist zu einem Zeiger zerfallen. In diesem Fall müssen Sie verwenden sizeof(*dst)*ARRAY_LENGTH.

  • +1, aber ich glaube nicht, dass “statisch” der richtige Begriff für eine Variable vom Typ Array ist. Es könnte eine automatische sein, und “statisch” hat bereits viele Bedeutungen in C und insbesondere in C++. Ihr “ie” ist eher so.

    – Steve Jessop

    21. April 2010 um 8:07 Uhr


Benutzer-Avatar
Mark_Carrington

Unter der Annahme, dass dst vom Typ int* ist, gibt sizeof(dst) die Größe des Zeigers selbst zurück (dh 4 auf einem 32-Bit-System, 8 auf einem 64-Bit-System), sodass Ihr zweites Beispiel nur jede dieser vielen Bytes kopiert, während Die erste verwendet korrekt die tatsächliche Größe des Inhalts.

  • +1, aber ich glaube nicht, dass “statisch” der richtige Begriff für eine Variable vom Typ Array ist. Es könnte eine automatische sein, und “statisch” hat bereits viele Bedeutungen in C und insbesondere in C++. Ihr “ie” ist eher so.

    – Steve Jessop

    21. April 2010 um 8:07 Uhr


Benutzer-Avatar
el.pescado – нет войне

Wird die zweite Option immer funktionieren? Unabhängig vom Inhalt?

Es funktioniert nur, wenn beide Bedingungen erfüllt sind:

  • dst ist ein reguläres Array, kein Zeiger
  • src und dst sind gleich groß

  • Oder src ist größer als dst.

    – Traumlax

    21. April 2010 um 7:43 Uhr

1353380cookie-checkmemcpy(), welchen Wert sollte der Größenparameter haben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy