2017-02-05 2 views
1

Je suis capable de "pack" des tableaux de longues chaînes. Maintenant, si je mémcpy la chaîne contenant des tableaux de long, le contenu est perdu. Ici vous avez mon code:Copier des chaînes contenant des longs

#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))); 
    } 
} 

Et ceci est la sortie:

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 

Comme vous pouvez le voir, je suis en mesure de lire les valeurs longues que j'ai magasin dans « arr » mais pas de " arr2 ". Une idée?

+3

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

+2

(long *) arr2 + i * sizeof (long) 'entraînera un comportement indéfini dû à l'accès au tampon hors limites. '(long *) arr2 + i' est déjà indexé dans' sizeof (long) ' – StoryTeller

+1

Merci ** tout ** pour vos réponses et vos commentaires. Malheureusement, je peux accepter seulement l'un d'eux ... – mauro

Répondre

1

Lorsque vous ajoutez 1 à pointeur se p et sizeof(*p) == 8, il est équivalent à l'ajout 8 à un pointeur char. En d'autres termes, une fois que vous avez lancé le pointeur, il n'est plus nécessaire de redimensionner l'index.

#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))); 
    } 
} 

Techniquement cependant, votre programme est encore non défini parce qu'elle viole aliasing strict. Vous pouvez résoudre cela en utilisant un tableau long et en y accédant via un pointeur char, en utilisant de la mémoire dynamique au lieu de tableaux alloués par pile, ou en notant les octets char dans un long temporaire à chaque itération de la boucle (gcc peut prendre la indice et la dernière solution ne finit pas par être inefficace, malgré ce qui semble être un appel de fonction apparemment cher).

+0

@StoryTeller Eh bien, c'est ce que j'ai suggéré comme solution. Cependant, le programme ci-dessus ne respecte pas l'aliasing strict (d'abord '' ((long *) arr + i) = f; ') car il utilise un pointeur long pour accéder à un tableau char, et non l'inverse. – PSkocik

+0

Après une lecture attentive, je me trompe vraiment. Bien que si un tableau de caractères avec stockage automatique est toujours désiré, le problème pourrait être atténué par le biais du type d'union-punning, me pense-t-il. (les valeurs de trappe ne résistent bien sûr pas). – StoryTeller

+0

@StoryTeller Parfois, j'utilise alloca (je l'utilise à la place des VLA parce que je peux encore passer l'allocation) et prétendre que c'est comme de la mémoire mallocée. – PSkocik

1

Le problème est que l'on vous lancez la (pourrie) pointeur arr et arr2 à un long*, alors vous n'avez plus d'octets ob tableau mais un tableau de long de sorte que votre pointeur arithmétique ne sera plus correct (il prend la pointeur est un pointeur de char). Déposez la multiplication, et faites juste par exemple.

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

(long *)arr2 + i*sizeof(long) entraînera un comportement indéfini en raison de l'accès au tampon hors limites. (long *)arr2 + i est déjà indexé dans sizeof(long).

Donc, vous écrivez bien au-delà de la fin de arr, mais copiez seulement les 40 premiers octets de celui-ci. Au-delà, il n'y a pas de raison de raisonner sur un comportement indéfini. Si vous aviez été chanceux, il se serait écrasé, donnant ainsi une indication immédiate que vous avez fait quelque chose de terriblement mal.

1

Votre problème est dans plusieurs expressions

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

Vous devez décider si vous faites l'arithmétique des pointeurs sur des pointeurs char, ou long pointeurs.

Si vous voulez le faire sur char pointeurs, vous commencez avec arr, ajouter i * sizeof (long), et se convertir à un pointeur long:

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

D'autre part, vous pouvez également convertir arr à un pointeur long en premier.Mais alors, vous n'avez pas à multiplier par sizeof(long), parce que l'arithmétique des pointeurs sur long fonctionne en unités de sizeof(long), pas d'octets:

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