I'm sure that the answer to this is me not understanding Pointers and References properly!
So at the start of my C file I define a struct for people:
typedef struct {
char id[4];
int age;
char name[128];
} people;
Then inside of main() I create an array of 10 people structs called record.
people* record = (people*)malloc(sizeof(people)* 10);
In main() we start and then dive off into a function with
MyFunction(record);
(This function is prototyped at the beginning of the C file before main() with
int MyFunction(people *record);
Inside of MyFunction() we do various stuff, including wanting to increase the record array size so that it can hold more people structs.
I'm attempting to increase the record array size with
struct people *tmp = realloc(record, 20 * sizeof (people));
if (tmp)
{
record = tmp;
}
But this doesn't work and I get memory corruption if I attempt to use the newly added structs in the array.
As I said, I'm sure that this is due to me not understating Pointers and References properly.
Note that I can't have MyFunction() give an expanded record array as its return type because I'm already using its return int for something else (and I'm not sure I'd get that to work properly either!) - I need it to be using the main record array.
Can anyone point me in the right direction please?
int MyFunction(people **record);// MyFunction(&record);//call at main
...
struct people *tmp = realloc(*record, 20 * sizeof (people));
if (tmp)
{
*record = tmp;
}
Related
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.)
I tried to create a struct that would incude a dynamic array:
typedef struct
{
int idNode;
int* n; //pointer to the int nodes in the dynamically created array of nodes
n = calloc(MAX, sizeof(int)); //dynamic array to store the loser member of the pair
int counter = 0;
}
node;
But I get
error: type name requires a specifier or qualifier
You cannot assign a value to n in the struct declaration. You need to provide a function (something like a constructor ;-) that initializes the structure and assigns a value to its members, including n:
void init_node(node* n)
{
n->idNode = ...;
n->n = calloc(MAX, sizeof(int));
n->counter = 0;
}
Note: you still need to handle errors (e.g. calloc may fail) in the function and propagate errors to its caller.
You can't have statements or initialize an variable inside a structures.
For fix your problem
typedef struct Node {
int idNode;
int* n; //pointer to the int nodes in the dynamically created array of nodes
int counter;
} node;
int main(void)
{
node data = null;
node.n = calloc(sizeof(int), MAX);
node.idNode = 0;
node.counter = 0;
return (0)
}
Now you have initialize your struct
Starting point
I tried to create a struct that would incude a dynamic array
The problem I see in your initial snippet is you mix definition, declaration and use.
From https://www.geeksforgeeks.org/difference-between-definition-and-declaration:
Declaration of a variable is for informing to the compiler the following information: name of the variable, type of value it holds and the initial value if any it takes. i.e., declaration gives details about the properties of a variable. Whereas, Definition of a variable says where the variable gets stored.
Steps to get a basic knowledge of how to do it.
Firstly, you must know how to create a struct.
The next step is how to typedef it.
The next step is how dynamic arrays are declarated, defined, created, stored, modified or destroyed (the life cycle). Pay attention to erros may occur during the execution. The happy path of create things in C is not the only one, there are plenty of errors out there!
The next step is how to insert them into a typedef'd struct.
And the last step is use that typedef struct with a dynamic array inside it. Even you can create multiple dynamic arrays in the struct!
Note: Steps, 1, 2 and 4 may be ordered in other ways depend on the programmer
There is no shortcuts, no trial and error and, of course, you must create test programs to ensure the stuff you want and the stuff you program are the same thing.
n = calloc(MAX, sizeof(int));
int counter = 0;
You cannot use statements to execute inside of the declaration of a structure. You need to initialize n and counter inside of a function after an object of node has been defined.
E.g.:
typedef struct
{
int idNode;
int* n;
int counter;
}
node;
int main (void)
{
node a;
a.n = calloc(MAX, sizeof(int));
a.counter = 0;
}
I'm going to try and keep this as brief as possible.
So I have two structs:
typedef struct someStruct named;
struct someStruct {
void *key;
void *value;
};
typedef struct anotherStruct namedToo;
struct anotherStruct {
named **table;
unsigned int size;
};
Okay great, now ingore any possible mistakes above, this is uneditable code.
Now I have two methods:
namedToo *init(float ignoreThis) {
namedToo *temp;
temp = malloc(sizeof(namedToo)); //some memory for the second struct
temp->table = malloc(sizeof(named)*100); //lets say this 100 is for 100 buckets/cells/named elements
return temp;
Method 2:
int insert(namedToo *temp, void* key, void* value) {
temp->table[0]->key = key; //My problem, I need to access the value and key inside named from the pointer inside namedToo. How can I do this?
}
The comment has my problem :
My problem, I need to access the value and key inside named from the pointer inside namedToo. How can I do this? I would need to change and grab value/key on their own from time to time.
The declaration named **table; says table is pointer to a pointer to named, or alternately an array of pointer to named. The latter is you seem to intend.
This allocation:
temp->table = malloc(sizeof(named)*100);
Allocates space for 100 named, but what you need are 100 named *, and each of those must point to a named. Given the definition of named this is likely enough space, however at this point you have an array of uninitialized pointers. Attempting to access them results in undefined behavior, which in this case manifests as a core dump.
You need to allocate space for an array of pointers, then initialize each of those to a single dynamically allocated instance of named. So you should be allocating space like this:
int i;
temp->table = malloc(sizeof(named *)*100);
for (i=0; i<100; i++) {
temp->table[i] = malloc(sizeof(named));
}
Then your insert method should work properly.
I'm working on a practice exercise and it seems printf() is writing over my variable somewhere. I'm working with a structure containing a pointer to an array of pointers to structures so I'm sure I've assigned something slightly wrong somewhere.
int dictionary_add(struct dictionary* d,
const char * const english,
const char * const foreign){
/* ROLE Adds a new wordPair made of strdup copies of the parameter strings
to a dictionary d
RETURNS 0 if everything went fine
PARAMETERS d the dictionary to work with
english string representing the english part of the new wordPair
foreign string representing the foreign part of the new wordPair
*/
//Determine where in the array the wordPair is going.
int location;
location=((d->size)-(d->nbwords))-1;
printf("Adding data to array location: %i\n\n",location);
//Build the wordPair
const struct wordPair newPair={english,foreign};
//Add the wordPair
d->data[0]=&newPair;
//***************This is where the problem shows up***************
printf("Added english:%s\n",d->data[0]->englishWord);
//d->data[0]=&newPair; //When uncommeted, program doesn't crash.
printf("Added english:%s\n",d->data[0]->englishWord);
d->nbwords++;
return 0;
}
How this is called from main():
const char* english=malloc(sizeof(char)*6);
const char* foreign=malloc(sizeof(char)*6);
strcpy(english,"hello");
strcpy(foreign,"holla");
Where the dictionary is created:
struct dictionary *dictionary_build(int size){
/* ROLE Allocate and initialize a new dictionary structure able to accomodate a number of
pairs of words specified by the size parameter
RETURNS Address of new dictionary, if allocation was successfull.
NULL otherwize
PARAMETERS The size of the dictionary to make
*/
struct dictionary *d=malloc(sizeof(struct dictionary));
d->size=size;
d->nbwords=0;
struct wordpair* wordPairs[size]; //create array of pointers to wordpairs
d->data=&wordPairs; //Set pointer to array of pointers to wordpairs
return d;
}
The structures:
struct wordPair {
char* englishWord;
char* foreignWord;
};
struct dictionary {
struct wordPair ** data;
int nbwords;
int size;
};
Thanks in advance for any help. And I'm not opposed to the idea that my entire design misses the point. I can change anything outside of the struct definitions and the expected parameters.
When you do this:
struct wordpair* wordPairs[size];
d->data=&wordPairs;
return d;
}
wordPairs has automatic storage, and its lifetime will end when the function returns. It's undefined behavior to attempt to refer to an object after the end of its life, yet you are retaining a pointer to it within d which you then try to dereference in dictionary_add().
Use something like d->data = malloc(size * sizeof(struct wordpair *)); or similar, instead. Don't forget to check the return from malloc() to determine whether it succeeded, and (usually) to free() everything when you're done.
i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]