2017-02-05 3 views
1

Ich bin in der Lage, lange Arrays in Strings zu "packen". Jetzt, wenn ich die Zeichenfolge mit langen Arrays memcpy, der Inhalt ist verloren. Hier haben Sie meinen Code:Strings mit Longs kopieren

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    unsigned char arr[40]; 
    unsigned char arr2[40]; 
    unsigned int i = 0 ; 
    long f=0; 

    for (i = 0 ; i < 5 ; i++) { 
     f = i + 1 ; 
     *((long *)arr + i*sizeof(long)) = f ; 
    } 
    memcpy(arr2, arr, 40); 
    for (i = 0 ; i < 5 ; i++) { 
     f = *((long *)arr2 + i*sizeof(long)) ; 
     printf("f =%ld from arr2 sizeof %zu\n", f, (size_t)(i*sizeof(long))); 
    } 
    for (i = 0 ; i < 5 ; i++) { 
     f = *((long *)arr + i*sizeof(long)) ; 
     printf("f =%ld from arr sizeof %zu\n", f, (size_t)(i*sizeof(long))); 
    } 
} 

Und dies ist die Ausgabe:

f =1 from arr2 sizeof 0 
f =0 from arr2 sizeof 8 
f =1 from arr2 sizeof 16 
f =140734674541394 from arr2 sizeof 24 
f =140734674541702 from arr2 sizeof 32 
f =1 from arr sizeof 0 
f =2 from arr sizeof 8 
f =3 from arr sizeof 16 
f =4 from arr sizeof 24 
f =5 from arr sizeof 32 

Wie man sehen kann ich in der Lage bin, die langen Werte lesen Ich habe Speicher in „arr“, aber nicht aus " arr2 ". Irgendeine Ahnung?

+3

'i * sizeof (long)' -> 'I' – BLUEPIXY

+2

' (long *) arr2 + i * sizeof (long) 'führt zu undefiniertem Verhalten aufgrund von Pufferzugriff außerhalb des gültigen Bereichs. '(long *) arr2 + i' indexiert bereits in' sizeof (long) ' – StoryTeller

+1

Danke ** all ** für deine Antworten & Kommentare. Leider kann ich nur einen von ihnen akzeptieren ... – mauro

Antwort

1

Wenn Sie 1 hinzufügen p und sizeof(*p) == 8 auf Zeiger, es auf das Hinzufügen 8 zu einem char Zeiger gleichwertig ist. Mit anderen Worten, sobald Sie den Zeiger umgesetzt haben, müssen Sie den Index nicht mehr skalieren.

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    unsigned char arr[40]; 
    unsigned char arr2[40]; 
    unsigned int i = 0 ; 
    long f=0; 

    for (i = 0 ; i < 5 ; i++) { 
     f = i + 1 ; 
     *((long *)arr + i) = f ; 
    } 
    memcpy(arr2, arr, 40); 
    for (i = 0 ; i < 5 ; i++) { 
     f = *((long *)arr2 + i) ; 
     printf("f =%ld from arr2 sizeof %zu\n", f, (size_t)(i*sizeof(long))); 
    } 
    for (i = 0 ; i < 5 ; i++) { 
     f = *((long *)arr + i) ; 
     printf("f =%ld from arr sizeof %zu\n", f, (size_t)(i*sizeof(long))); 
    } 
} 

Technisch aber Ihr Programm ist noch nicht definiert weil es strenge Aliasing verletzt. Sie könnten das lösen, indem Sie ein Array von long verwenden und über einen char-Zeiger darauf zugreifen, indem Sie dynamischen Speicher anstelle von stack-allocated-Arrays verwenden oder indem Sie die char-Bytes in jeder Iteration der Schleife in ein temporäres long speichern (gcc kann die Hinweis und die letzte Lösung ist schließlich nicht ineffizient, obwohl es sich scheinbar um einen teuren Funktionsaufruf handelt).

+0

@StoryTeller Nun, das habe ich als Lösung vorgeschlagen. Das obige Programm verletzt jedoch striktes Aliasing (zuerst bei '* ((long *) arr + i) = f;'), weil es einen langen Zeiger verwendet, um auf ein char-Array zuzugreifen, und nicht umgekehrt. – PSkocik

+0

Nach sorgfältiger Lektüre täusche ich mich tatsächlich. Obwohl, wenn ein Char-Array mit automatischem Speicher immer noch gewünscht wird, könnte das Problem über Union-Typ-Punning gemildert werden, denkt ich. (Fallenswerte natürlich nicht aushalten). – StoryTeller

+0

@StoryTeller Manchmal verwende ich alloca (ich benutze es anstelle von VLAs, weil ich dann immer noch über die Zuweisung springen kann) und tue so, als wäre es ein Malloc-Speicher. – PSkocik

1

Das Problem, dass man Sie (verfallenen) gegossen ist Zeiger arr und arr2 zu einem long*, dann haben Sie nicht mehr ein Array ob Bytes, sondern eine Reihe von long so Ihre Pointer-Arithmetik nicht mehr korrekt sein (es nimmt die Zeiger ist ein Zeiger von char). Lassen Sie die Multiplikation fallen und tun Sie z.B.

*((long *)arr + i) = f ; 
2

(long *)arr2 + i*sizeof(long) führt zu undefiniertem Verhalten aufgrund von Pufferzugriff außerhalb der Grenzen. (long *)arr2 + i indexiert bereits in sizeof(long).

So schreiben Sie weit über das Ende von arr, aber kopieren Sie nur die ersten 40 Bytes davon. Darüber hinaus gibt es keinen Grund, über undefiniertes Verhalten nachzudenken. Hättest du Glück gehabt, wäre es abgestürzt, und du hättest sofort angedeutet, dass du etwas sehr falsch gemacht hast.

1

Ihr Problem ist in den verschiedenen Ausdrücken

*((long *)arr + i*sizeof(long)) 

Sie müssen entscheiden, ob Sie sich auf char Zeiger der Zeigerarithmetik tun, oder long Zeiger.

Wenn Sie es auf char Zeiger tun möchten, können Sie mit arr starten, fügen Sie i * sizeof (long) und konvertieren zu einem long Zeiger:

  arr 
     arr + i*sizeof(long) 
(long *)(arr + i*sizeof(long)) 

Auf der anderen Seite können Sie auch konvertieren arr zu einem long Zeiger zuerst.Aber dann müssen Sie nicht von sizeof(long) multiplizieren, weil Arithmetik auf long Zeiger in Einheiten von sizeof(long) arbeitet, nicht Bytes:

  arr 
(long *)arr 
((long *)arr + i) 
Verwandte Themen