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?
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
.
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.:)