How to assign null to pointer of struct? - c

I am not sure i'f i was specific and clear enough.
But ill clear the doubt.
I am trying to assign a NULL value to a pointer.
given the code :
typedef struct Date
{
int year;
int month;
}Date;
typedef struct Record
{
char name[20];
char cdate[20];
float quanitity;
int barcode;
Date date;
}Record;
and then in main :
Record *records = malloc(10 * sizeof(Record));
records[0] = NULL;
This just doesn't work, when I define a similliar array of premitive type, for example int
I can assign values, or NULL
For example for
int *avi = malloc(sizeof(int)*10);
avi[0] = 3;
avi [0] = NULL;
It works fine, i've printed the values and seen the changes.
However when I do the same for an array of pointers to struct, as defined above
I just can not assign a NULL value..
clueless.
I am using eclipse IDE.
thanks in advance.

Your problem is that records is a pointer to 10 objects. Thus, records[0] is the first object. You cannot set the object to NULL.
It only appears to work for int because you set the int to zero, not NULL.

NULL is a built in constant which has a value of 0. That's why you can assign it to primitive types such as int and char. It works for pointers due to a specific construct of the C language that tells the compiler that "0" means "point to an invalid memory address", which may not be the actual value "0".
Your assignment of NULL to a structure type doesn't work because you can't set a structure to an integer type.

Here is an example of creating an array of pointers to Record structures. Because the array contains pointers to the Record structures instead of containing the structure directly the pointers can be set to NULL - something you can't do if the array contains the Record structure directly.
#include <stdlib.h>
typedef struct Date
{
int year;
int month;
}Date;
typedef struct Record
{
char name[20];
char cdate[20];
float quanitity;
int barcode;
Date date;
}Record;
int main()
{
// We start by creating an array of 10 Record pointers.
// records is a pointer to the array we create
Record **records = malloc(10 * sizeof(Record*));
// First thing is first - did it work?
// There is no point in doing anything else if the array didn't get created
if (records != NULL) {
// The Record pointers are uninitialized
// Arrays don't do that automatically
// So we need to initialize all the pointers
// in this case we set them all to NULL
for (int i=0;i<10;i++)
records[i] = NULL;
// Later on in the program we might want to
// create one Record structure and assign it to records[5]
records[5] = malloc(sizeof(Record));
// Again, we need to check if the Record structure got created
if (records[5] != NULL) {
// Do something with this Record structure
// Fill it in, print it out, etc.
}
// Then at the end of the program
// we want to deallocate all the Record structures we created
for (int i=0;i<10;i++)
if (records[i] != NULL)
free(records[i]);
// And finally we need to deallocate the array of pointers
free(records);
}
return 0;
}

Related

C error: type name requires a specifier or qualifier

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

Understanding pointer structs in C

I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)

Expand an array with realloc inside of a function - Pointers?

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

C- printf() is writing over my variables

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.

How to correctly define an array of structures?

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]

Resources