dynamically allocate memory for pointer to array of structure - c

hi i have this structure
typedef struct STUDENT
{
char studName[20];
int timeEnter;
int timeUpdate;
}STUDENT;
and the local pointer to array of structure
STUDENT *studArr[100];
I'm trying to allocate memory for the structure by doing reading in the first line of the file then use it to allocate memory for the structure.
fscanf(fp, "%s", &first);
**studArr = (STUDENT**) malloc(sizeof(STUDENT*)*first);
I got an error saying that no operator "=" matches these operands on the allocation line
why am I gettting the error, what did i do wrong here?
thank in advance

I think you're confusing things, it looks like you're declaring an array of pointers, when all you need is a single pointer. Note that as long as you're indexing properly, a pointer to "one" struct is the same as a pointer to a hundred.
You should probably have:
STUDENT *studArr;
then, once you know how many you need (I'm assuming first is the number of students to allocate room for):
studArr = malloc(first * sizeof *studArr);
Also note that no casting is needed.

If you want to allocate an array of 100 students, you have two choices:
struct STUDENT
{
char studName[20];
int timeEnter;
int timeUpdate;
};
struct STUDENT studArr1[100];
... OR ...
struct STUDENT *studArr2 = (struct STUDENT *)malloc (sizeof (struct STUDENT) * 100);
If you just want a pointer, you can say:
struct STUDENT *p = studArr1;
PS:
I deliberately left the "typedef" stuff out so as not to confuse the basic issue (struct vs. array of struct vs pointer to array of struct).

You have defined an array of pointers to struct, not a pointer to an array of struct. The memory for the array is already allocated, as a global array.
The type of **studArr is STUDENT, and hence is not compatible with the expression to the right of the assignment operator, which is casted to (STUDENT**).
You probably meant:
STUDENT **studArr;
[...]
fscanf(fp, "%s", &first);
studArr = (STUDENT**) malloc(sizeof(STUDENT*)*first);

As you are using STUDENT *studArr[100]; then it means you have allocated the memory for 100 pointers for STUDENT structure type.
so for allocating the memory you should try.
studArr =malloc(sizeof(struct STUDENT)*first);
then you can access all the allocated members as studArr[i] ....so on.

You're not exactly clear on what your overall goal is.
First of all, you want to use %d if you want to read in an integer:
int count;
if (fscanf(fp, "%d", &count) != 1) { // error... }
Next, don't use STUDENT as both the struct name and the typdef. Just leave the struct name out:
typedef struct
{
char studName[20];
int timeEnter;
int timeUpdate;
} student_t;
Now, you're going to want just a pointer to an array of student_ts:
student_t* student_array = NULL;
Finally, allocate that array:
student_array = malloc(count * sizeof(student_t));
Now you can use it, like:
strncpy(student_array[0].studName, "Bobby", 20);
Or get a pointer to an individual student:
student_t* bob = &student_array[1];
bob->timeEnter = 42;

Related

Malloc'ing a double pointer structure inside a struct?

C noob here. I'm trying to initialize a simple struct as follows:
typedef struct person_s {
char *fname; ///< first name of the person
char *lname; ///< last name of the person
char *handle; ///< handle of the person
struct person_s **friends; ///< dynamic collection of friends
size_t friend_count; ///< current number of friends
size_t max_friends; ///< current limit on friends
} person_t;
I think I understand using malloc for every single member in this struct, except for the double pointer friends struct in it. How do I allocate memory for this double pointer?
Here's my malloc for the other data members:
person_t *newperson(char *fn, char *ln, char *han){
person_t *p = NULL;
p = malloc(sizeof(person_t));
p->fname = malloc(strlen(fn) +1);
strcpy(p->fname, fn);
p->lname = malloc(strlen(ln) +1);
strcpy(p->lname, ln);
p->handle = malloc(strlen(han) +1);
strcpy(p->handle, han);
p->*friends = malloc(sizeof(*friends));
p->friend_count = malloc(2*sizeof(friend_count));
p->friend_count = 0;
p->max_friends = malloc(2*sizeof(max_friends));
p->friend_count = 0;
}
Edit: my bad, I forgot to include that this is inside a function that initializes this struct.
Edit1: In response to the comments, what I'm trying to achieve here is to make a dynamic "array" of friends that is pointed by the p->friends data member. Additionally, I have a dynamic hash table, would it be a good idea to use it as a collection for putting all the friends linked to this person? The concept of pointers and dynamic allocation is still somewhat confusing to me so sorry for misunderstanding.
Single pointer is enough for dynamic collection:
struct person_s *friends;
...
p->friends = malloc(max_friends * sizeof(struct person_s));
First of all keep the syntax simple, let us assume you have typedefed struct person_s as person.
A pointer to pointer is the same thing as a pointer to an array of pointers.
So, first you need to allocate the array, then you need to allocate individual elements within the array.
This will allocate the array:
friends = malloc(max_friends * sizeof(*friends));
This works, because friends is of type **person, so *friends must be of type *person.
Then, you will need a for loop in which you allocate each person:
friends[i] = malloc(sizeof(**friends)); //or sizeof(person), same thing.
(I typed the above immediately after the question was posted, only to find out that the question was closed before I had the chance to answer. Then later the question was opened, but I was never notified. I am posting it because I would hate to just throw it away now.)

calloc sometimes gives double the amount of memory asked

I came across something I don't understand why and I'd like to hear an explanation about it.
I have this struct:
typedef struct Student {
int age;
char *name;
} Student;
int main()
{
Student **test1 = calloc(2, sizeof(*test1));
Student **test2 = calloc(2, sizeof(**test2));
return 0;
}
I've noticed that test1 gets 2 memory allocations (as it should) while test2 gets 4. Why is that and which is the correct usage? I assume its the first one but i'm not sure why.
Thanks!
sizeof(*test1) is the size of a pointer Student*, while sizeof(**test) is the size of a structure Student.The structure has a pointer, so its size should be larger than the size of a pointer.
Student **test1 = calloc(2, sizeof(*test1));
Is the typical usage. This is allocating 2-element array of Student* and assigning the pointer to its first element to test1.
Two things here:
You're allocating two different amounts of memory here. In the first case, you allocate space for 2 objects of type Student *, while in the second case you allocate space for 2 objects of type Student. The latter is likely larger than the former, so you'll be able to put more object of type Student * there.
You don't show how you're verifying how much memory you've gotten, but it's undefined behavior to read or write past the bounds of allocated memory. Your program might crash, or it might not.
sizeof(*test) is a size in bytes of the pointer to Student. It will be on most systems 4 or 8.
sizeof(**test)gives you the size of the Student. The allocation (test2) makes no sense at all.
You can easily test it yourself by printing the sizes:
#include <stdio.h>
#include <malloc.h>
typedef struct Student {
int age;
char *name;
double somedata[100];
} Student;
int main()
{
Student **test1;
Student **test2;
printf("%zu\n", sizeof(*test1));
printf("%zu\n", sizeof(**test2));
return 0;
}
https://godbolt.org/z/W6e8YzKKf

C, Expression must be a modifiable lvalue (changing the value of a struct's member) [duplicate]

This question already has answers here:
Assigning strings to arrays of characters
(10 answers)
Closed 4 years ago.
I'm an extreme newbie, I'm just trying to learn.. this is my simple struct that I've created
struct Student{
char FirstName[20];
char LastName[20];
char StudentID[10];
char Password[20];}
Then I'm creating an array of pointers;
struct Student *StudentList[10];
I am then calling my "Register" function and passing the first element in the array as a parameter, for the reason of changing values to that specific struct element in the array, for example I want to change the student's details;
Register(&StudentList[0]);
Further on, my function;
void Register(struct Student *student);
void Register(struct Student *student) {student->FirstName = "John";}
This is a very simplified example and sorry for not being able to correctly paste in the code here.
But why am I getting an "expression must be a modifiable lvalue", when I try to assign a value.
You can't assign array types like that in C, and "John" is an array of type char[5].
strcpy(student->FirstName, "John");
would do it or, better still, something of the form
strncpy(student->FirstName, "John", 20);
so you avoid overrunning the char buffer.
The firstName field is an array, and arrays cannot be assigned to as a whole. That's what the error message is telling you.
Since you're copying a string into this array, you should use strcpy:
strcpy(student->FirstName, "John");
In C, you do not set strings using = (and you do not compare them using == either).
You must use the strcpy function:
strcpy( student->firstName, "John" );
First thing you forget to put semicolon at the end of struct declaration struct Student { };
Secondly, you are passing &StudentList[0], instead just pass StudentList[0] and allocate memory dynamically for that first.
Finally, student->FirstName = "John"; because student->FirstName is one char buffer and "John" also one buffer so you can't do A = B where A and B both are char buffer, instead use strcpy(A,B);
Here is sample example
struct Student{
char FirstName[20];
char LastName[20];
char StudentID[10];
char Password[20];
}; /* you forget to put semicolon */
void Register(struct Student *student) {
strcpy(student->FirstName,"John"); /* use strcpy() */
printf("%s\n",student->FirstName);
}
int main() {
struct Student *StudentList[10];
for(int index = 0;index < 10;index++) {
StudentList[index] = malloc(sizeof(struct Student)); /* allocate memory for each Student */
}
Register(StudentList[0]);
/* free the dynamically allocated memory */
return 0;
}

Struct With Pointer Usage, SEGMENTATION FAULT

I have a little problem with using struct array in C. It returns me segmentation fault
struct Yset{
char *unit;
char *name;
char *showValue;
char *fillColor;
char *yData;
};
struct Yset *svg_ysets;
int ySetCounter = 0;
svg_ysets[ySetCounter].unit = malloc(strlen((char*)attribute)+1);
strcpy(svg_ysets[ySetCounter].unit,(char*)attribute);
printf("%s\n", svg_ysets[ySetCounter].unit);
ySetCounter++;
What's wrong with this using? I dont know the number of Ysets so it must be dynamic. Thanks
svg_ysets[ySetCounter].unit = malloc(strlen((char*)attribute)+1);
You are dereferencing pointer to structure while the pointer doesn't point to meaningful place. In other words you didn't allocate space to hold the structure object itself.
// allocate five objects
struct Yset *svg_ysets = malloc (5 * sizeof(struct Yset));
Don't forget to free if you are using dynamically allocated memory somewhere.

Using malloc to initialize char *vals[SIZE] in a struct

I have a struct like this:
struct students {
char *names[MAXLENGTH];
};
How would I initialize the struct using malloc?
I tried
struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
but that gave me a "missing braces around initializer" error.
I'm new to C, so I'm not sure how to fix this.
You can allocate an instance of the struct like this:
struct students *pStudent = malloc(sizeof *pStudent);
This will allocate the array of string pointers (since it's part of the struct students), but not set the pointers to point at anything (their values will be undefined).
You need to set each individual string pointer, for instance like so:
pStudent->names[0] = "unwind";
This stores a pointer to a literal string. You can also allocate memory dynamically:
pStudent->names[1] = malloc(20);
strcpy(pStudent->names[1], "unwind");
of course, if you malloc() space you must remember to free() it. Don't mix literal strings with dynamically allocated ones, since it becomes impossible to know which ones need free()ing.
This is totally wrong struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
Try this code.
struct students* Student1 = malloc(sizeof(struct students ));
Student1->names[0] = malloc(sizeof(NAME_MAX));
scanf("%s",Student1->names[0]);//It may be first name. I think you want like this .
You have to use a for loop like this :
#define MAX_NAME_LENGTH 20
struct student s;
for(int i = 0; i < MAXLENGTH; ++i)
{
s.names[i] = malloc(sizeof(char) * MAX_NAME_LENGTH);
}

Resources