Flexible array member not getting copied when I make a shallow copy of a struct

帅比萌擦擦* 提交于 2019-11-26 18:38:19

问题


I have made a shallow copy a struct I have in the following manner:

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
}

When I check the first element of the flexible array member it oneCopy, it is null. But if I check the first element of the flexible array member in the original struct it prints out the pointer successfully. All the other components of the original struct are copied over like the name and the linked list. It is only the flexible array member that is not getting copied. Does anyone know what I am doing wrong?


回答1:


Does anyone know what I am doing wrong?

Trying to use assignment to copy a struct with a flexible array member. From the standard (6.7.2.1):

The assignment *s1 = *s2 only copies the member n [i.e. the part of the struct that isn't a flexible array]; if any of the array elements are within the first sizeof (struct s) bytes of the structure, they might be copied or simply overwritten with indeterminate values.

Basically, when the C compiler sees a struct with a flexible array member, it doesn't know how big it really is, so it treats it as being big enough to hold the other members, plus possibly some more:

In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.

That's what sizeof(*one) is, and that's the size of what gets copied when you do *oneCopy = *one;.

Since you do apparently know the size of the entire structure, in order to malloc it, just copy that many bytes using memcpy. Or if you're concerned that that's somehow unportable (honestly I'm not sure), do the assignment, then use a loop to copy each element from one->friends to
oneCopy->friends.




回答2:


In your code snippet the structure declaration is wrong. I think you mean a typedef of a structure instead of declaring an object of the structure.

For example

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

This call of malloc is also wrong

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

There should be

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

Here is a demonstrative program that shows how the function can be written

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

Its output is

Age = 20

Take into account that it is desirable that the structure also contains a data member that will store the number of elements in the flexible array.:)



来源:https://stackoverflow.com/questions/35423293/flexible-array-member-not-getting-copied-when-i-make-a-shallow-copy-of-a-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!