Home > Software engineering >  Create struct array by a function C
Create struct array by a function C

Time:03-02

I want to create a function that creates an array of structures. What I have done is the following:

struct Student {
    char studentNames[128]; 
    unsigned int FN; 
    short selectiveDisciplinesList[10]; 
    unsigned short countOfSelectiveDisciplines; 
    bool hasTakenExams;
};
    
void fillInStudentInfo(Student &student) {...}

Student createStudentsArray() {
    unsigned int countOfStudents;
    std::cout << "Enter the number of students You are going to write down: " << std::endl;
    std::cin >> countOfStudents;
    Student studentsArray[countOfStudents];

    for (int i = 0; i < countOfStudents;   i) {
        fillInStudentInfo(studentsArray[i]);
    }

    return *studentsArray;
}

However, when in main(), I assign:

Student studentArray = createStudentsArray();

I can not access the members of each different struct (f.e. studentArray[i].something).

Where does the issue come from?

If I do it like this:

Student * createStudentsArray() {
    ...
    return studentsArray;
}

with

Student * studentArray = createStudentsArray();

My IDE warns me:

Address of stack memory associated with local variable returned

But I do seem to be able to access the members of each struct. Is that a bad thing?

CodePudding user response:

You really cannot do what you are trying to do in that way:

Student createStudentsArray() {
    ...
    Student studentsArray[countOfStudents];
    ...
    return *studentsArray;
}

Firstly, this is using a variable length array, which strictly speaking is invalid C . My compiler, for example, doesn't allow it.

Second, it will only return one Student. Even if it returned them all, its very inefficient because it would have to copy them all, but it doesn't.

You tried this:

Student *createStudentsArray() {
    ...
    Student studentsArray[countOfStudents];
    ...
    return studentsArray;
}

This is even worse. The memory allocated to that array is released once the function ends. This is what the compiler warned you about. Things seemed to work afterwards, but Very Bad Things(tm) will happen very soon afterwards.

Most experienced C devs will do this:

std::vector<Student> createStudentsArray() {
    ...
    std::vector<Student> students(countOfStudents);
    ...
    return students;
}

If you "are not allowed to use vector" (StackOverflow sees that all the time), then do:

Student *createStudentsArray() {
    ...
    Student *studentsArray = new Student[countOfStudents];
    ...
    return studentsArray;
}

But you must then delete[] that array once you are finished using it.

Footnote - for extra info, if you are really interested.

In fact, the experienced devs would do this:

std::vector<std::shared_ptr<Student>> createStudentsArray() {
    ...
    std::vector<std::shared_ptr<Student> students(countOfStudents);
    for (int......)
    {
        students.push_back(std::make_shared<Student>());
        ...
    }
    return students;
}

Now, the vector contains a bunch of smart pointers rather than the actual objects, that is the most efficient way to make arrays (or other containers) of largish objects. std::vector and std::shared_ptr will clean up all the memory for you automatically.

  • Related