2016-02-16 2 views
1

J'ai fait une copie superficielle d'une struct je de la manière suivante:membre flexible ne se copier quand je fais une copie superficielle d'une struct

struct Student{ 
     char *name; 
     int age; 
     Courses *list; //First course (node) 
     Student *friends[]; //Flexible array member stores other student pointers 
    }Student; 

void shallowCopy(const Student *one){ 
    Student *oneCopy = malloc(sizeof(one) + 20*sizeof(Student*)); 

    *oneCopy = *one;  <--------------- ERROR POINTS TO THIS LINE 
} 

Quand je vérifie le premier élément du tableau souple membre oneCopy, c'est null. Mais si je vérifie le premier élément du membre de tableau flexible dans la structure d'origine, il imprime le pointeur avec succès. Tous les autres composants de la structure d'origine sont copiés comme le nom et la liste chaînée. Seul le membre flexible du tableau n'est pas copié. Est-ce que quelqu'un sait ce que je fais mal?

+0

Vous semblez manquer quelques pointeurs dans votre code. 'oneCopy' semble être' Student * oneCopy' et 'friends' semble être' Student * friends [] '. –

+0

@MichaelAlbers Oui, vous avez raison, merci de l'avoir signalé. – Brandon

+0

Comment connaissez-vous le nombre d'éléments dans le tableau des amis? Je m'attends à voir une valeur de compte comme un autre champ dans la structure de Student. – ash

Répondre

3

Est-ce que quelqu'un sait ce que je fais mal?

Utilisation de l'affectation pour copier une structure avec un membre de groupe flexible. De la norme (6.7.2.1):

L'affectation *s1 = *s2 ne copie que membre n [à savoir la partie de la structure qui n'est pas un tableau flexible]; Si l'un des éléments du tableau se trouve dans les premiers octets de la structure, ils peuvent être copiés ou simplement remplacés par des valeurs indéterminées.

Fondamentalement, lorsque le compilateur C voit un struct avec un membre flexible, il ne sait pas quelle taille il est vraiment, il le traite comme étant assez grand pour contenir les autres membres, plus éventuellement un peu plus:

En particulier, la taille de la structure est comme si l'élément de réseau flexible était omis, sauf qu'il pourrait avoir plus de rembourrage arrière que l'omission impliquerait.

C'est ce que sizeof(*one) est, et qui est la taille de ce qui sera copié lorsque vous faites *oneCopy = *one;.

Puisque vous faites connaissent apparemment la taille de la structure, afin de malloc il, il suffit de copier que de nombreux octets en utilisant memcpy. Ou si vous craignez que ce soit quelque peu nonportable (honnêtement, je ne suis pas sûr), faire la cession, puis utiliser une boucle pour copier chaque élément de one->friends à
oneCopy->friends.

+0

Je ne pense pas que le problème que j'ai est un problème d'espace. Parce que juste pour le tester, j'ajoute la taille de 10.000 structs étudiant. Mais le pointeur est toujours nul. – Brandon

+0

@Brandon Je n'ai jamais suggéré que vous ayez un "problème d'espace". – hobbs

+0

pourriez-vous s'il vous plaît me montrer et exemple du changement que vous pensez que je devrais faire pour que je puisse comprendre – Brandon

0

Dans votre extrait de code, la déclaration de structure est erronée. Je pense que vous voulez dire un typedef d'une structure au lieu de déclarer un objet de la structure.

Par exemple

typedef struct Student 
^^^^^^^ 
{ 
    char *name; 
    int age; 
    Courses *list; //First course (node) 
    struct Student *friends[]; //Flexible array memeber stores other student pointers 
    ^^^^^^^^^^^^^^ 
} Student; 

Cet appel de malloc est également faux

Student *oneCopy = malloc(sizeof(one) + 20*sizeof(Student*)); 

Il devrait y avoir

Student *oneCopy = malloc(sizeof(*one) + 20*sizeof(Student*)); 
            ^^^^^ 

Voici un programme démonstratif qui montre comment la fonction peut être écrite

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

typedef struct Student 
{ 
    char *name; 
    int age; 
// Courses *list; //First course (node) 
    struct Student *friends[]; //Flexible array memeber stores other student pointers 
} Student; 

Student * shallowCopy(const Student *one, size_t friends) 
{ 
    Student *oneCopy = malloc(sizeof(Student) + friends * sizeof(Student *)); 

    *oneCopy = *one; 

    memcpy(oneCopy->friends, one->friends, friends * sizeof(Student *)); 

    return oneCopy; 
} 

int main(void) 
{ 
    Student *one = malloc(sizeof(Student) + sizeof(Student *)); 

    one->friends[0] = malloc(sizeof(Student)); 

    one->friends[0]->age = 20; 

    Student *oneCopy = shallowCopy(one, 1); 

    printf("Age = %d\n", oneCopy->friends[0]->age); 

    free(one->friends[0]); 
    free(one); 
    free(oneCopy); 
}  

Sa sortie est

Age = 20 

prendre en compte qu'il est souhaitable que la structure contient également un membre de données qui stockera le nombre d'éléments dans le tableau flexible. :)

+0

Pourrait également «memcpy» la structure entière tout à la fois. Je crois qu'en toutes circonstances, ce sera le plus rapide, et c'est le plus simple à lire et à comprendre. – ash