Pointer to Pointer to a structure in c - c

I have a simple structure.
struct grades
{
int lowest;
int highest;
};
Then I am to create a function that returns a pointer which initializes the structure.
struct *grades setGrades(int low, int high)
{
struct *ptr = malloc(sizeof(struct grades));
ptr->lowest = low;
ptr->highest = high;
return ptr;
}
Now I am supposed to make a function with definition struct **grades random(int size);
I am supposed to allocate space for an array of pointers to grade structures with the number of elements equal to size. When the array of pointers is created, I want to set each pointer in the array to a newly created data structure that has the low variable equal to 10 and high variable equal to 100 and then return pointer.
I am really lost at this point as I looked up double pointers to structures online but did not find any examples that can help me clear my understanding. I was wondering if someone can perhaps explain me how double pointers to structures work it would give me a Great start in the right directions.

A "double pointer" as you called it is simply a pointer to a pointer. That is, struct grade example is a variable that contains a lowest and a highest as you've defined. A pointer to that, struct grade *example is a variable that stores the memory address of the same structure. A pointer to a pointer, struct grade **example, is a variable that stores the memory address of a variable that stores the memory address of your structure. A more detailed explanation can be found here. Anyways, to answer your specific question, a function would be:
struct grades** random(int size) {
struct grades** result = malloc(sizeof(struct grades*) * size); //here you are
//allocating enough space for an
//array of pointers
int i;
for(i = 0; i < size; i++) {
result[i] = setGrades(10, 100); //here you are setting each pointer to one
//grade through the function you've already
//defined
}
return result;
}

struct grades { int lowest; int highest; };
struct grades * createGradeSet(int low, int high) //careful: return type is struct grades *
{
// variable name: ptr, type: struct grades *
struct grades * ptr = malloc(sizeof(struct grades));
ptr->lowest = low;
ptr->highest = high;
return ptr;
}
struct grades ** random(int size)
{
// Create a pointer to an array of struct grades pointers
// the size of the array is `size` x the size of a struct grades pointer
struct grades ** ptr_arr = malloc(sizeof(struct grades *) * size);
for (unsigned int i = 0; i < size; i++)
ptr_arr[i] = createGradeSet(10, 100); // assign a newly created Gradeset to every cell
return ptr_arr;
}

Try the following
struct grades ** random( size_t size )
{
if ( size == 0 ) return NULL:
struct grades **p = malloc( size * sizeof( struct grades * ) );
if ( p != NULL )
{
size_t i = 0;
do
{
p[i] = malloc( sizeof( struct grades ) );
if ( p[i] != NULL )
{
p[i]->lowest = 10;
p[i]->highest = 100;
}
} while ( p[i] != NULL && ++i < size );
if ( i != size )
{
for ( size_t j = 0; j < i; j++ ) free( p[i] );
}
free( p );
p = NULL;
}
return p;
}
Function setGrades should be written as
struct *grades setGrades( int low, int high )
{
struct *p = malloc( sizeof( struct grades ) );
if ( p != NULL )
{
p->lowest = low;
p->highest = high;
}
return p;
}
In this case the do while loop in the above function can be written as
do
{
p[i] = setGrades( 10, 100 );
} while ( p[i] != NULL && ++i < size );

Related

What is the use of i in `printf("%d\n",(a->ptr)[i]);`?

Hey guys I am currently learning DSA and in ADT I have a problem:
This is a code that creates a custom array and takes the input of the array and stores it and prints it too but I want to ask that what does that [i] do in printf("%d\n",(a->ptr)[i]); that thing is what I am not getting in this code
#include<stdio.h>
#include<stdlib.h>
struct myArray{
int total_size;
int used_size;
int *ptr;
};
void createArray(struct myArray * a,int tSize,int uSize)
{
a->total_size = tSize;
a->used_size = uSize;
a->ptr = (int *) malloc(tSize * sizeof(int));
}
void show(struct myArray * a){
for(int i=0; i < a->used_size; i++){
printf("%d\n",(a->ptr)[i]);
}
}
void setVal(struct myArray * a){
int n;
for(int i=0; i < a->used_size; i++){
printf("Enter Element %d: ", i);
scanf("%d",&n);
(a->ptr)[i] = n;
}
}
int main(){
struct myArray marks;
createArray(&marks,10,2);
printf("We are running setVal now\n");
setVal(&marks);
printf("We are running show now\n");
show(&marks);
return 0;
}
The data member ptr points to a dynamically allocated array
a->ptr = (int *) malloc(tSize * sizeof(int));
To access elements of the array you can use the subscript operator
printf("%d\n",(a->ptr)[i]);
To make it more clear consider the following code snippet.
enum { N = 10 };
int *ptr = malloc( N * sizeof( int ) );
for ( int i = 0; i < N; i++ )
{
ptr[i] = i;
}
The difference with the original code is the pointer ptr is a data member of a structure and to access ptr using a pointer to an object of the structure type you have to change in the code above the expression
ptr[i]
to
( a->ptr )[i]
that is the same as
a->ptr[i]
because there are used the postfix operator -> and [] that evaluates left to right.

Passing array of structs with reference - segmentation fault

#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X** a, int size){
for (int i = 0;i < size; i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container = (struct X*)malloc(sizeof(struct X) * n);
read_record(&container, n);
}
I created a 1D array of size n, then I passed it by reference to the function read_record. However, when I execute the program, there is a segmentation fault. What is the problem?
EDIT:
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. That's why I want to send the array as a reference. If I did it in main then I would write:
container = realloc(container, (n + 10) * sizeof(Struct X));
How can I do this in the function?
container is already a pointer, you don't need to pass the address-of the pointer, instead:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X *a, size_t size)
{
for (size_t i = 0; i < size; i++) {
a[i].deg = 0;
}
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
read_record(container, n);
}
also, prefer size_t to store the number of allocated objects.
Nitpick: read_record doesn't seem a good name for a function that modifies the contents of the records.
EDIT: As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
Same approach but returning a reallocated container:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
struct X *read_record(struct X *a, size_t size)
{
struct X *new = realloc(a, sizeof(struct X) * size);
if (new != NULL)
{
for (size_t i = 0; i < size; i++) {
new[i].deg = 0;
}
}
return new;
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
container = read_record(container, n * 2);
if (container == NULL)
{
fprintf(stderr, "Can't read record\n");
exit(EXIT_FAILURE);
}
}
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
The pointer is passed by value, so to save the changes and have them usable outside the function scope, after the function ends, i.e. in main, a pointer to pointer must be the argument, and the address of the pointer must be passed, your overall assessment is correct.
Your implementation, however, is not correct, here's how you shoud do it:
Live demo
void read_record(struct X **a, int size) //double pointer
{
*a = realloc(*a, sizeof **a * (size + 10)); //reallocate memory for 20 ints
if (*a == NULL)
{
perror("malloc");
}
for (int i = 0; i < size + 10; i++) //assing new values
{
(*a)[i].deg = 1;
}
}
int main()
{
int n = 10;
struct X *container = malloc(sizeof *container * n); //original allocation
//the pointer now has space for 10 ints
if (container == NULL)
{ //check allocation errors
perror("malloc");
}
for (int i = 0; i < n; i++) //assign values
{
container[i].deg = 0;
}
read_record(&container, n); //pass by reference
//the pointer now has space for 20 ints
}
Alternatively you can return the pointer instead, refering to David Ranieri's answer.
The first function parameter has the pointer to pointer type struct X**. So dereferencing the parameter a you will get a pointer of the type struct X*. Now you may apply the subscript operator that yields lvalue of the type struct X..
That is the function definition will look like
void read_record(struct X** a,int size){
for (int i=0;i<size;i++){
( *a )[i].deg = 0;
}
}
Or this statement
( *a )[i].deg = 0;
may be substituted for this statement
a[0][i].deg = 0;
On the other hand, there is no great sense to declare the first parameter as having the type struct X**. The function can look simpler as for example
void read_record(struct X* a,int size){
for (int i=0;i<size;i++){
a[i].deg = 0;
}
}
and be called like
read_record( container, n );
When you call read_record you pass a pointer to a pointer to the first element of an array of X structures.
But inside the read_record you treat it as a pointer to the first element of an array of pointers to X structures (i.e. as an array of pointers to X). There's a subtle but very important difference here.
If you want to emulate pass-by-reference for the pointer variable, you need to dereference it inside the read_record to get the original pointer (and remember that then you have an array of objects, not pointers):
(*a)[i].deg = 0;
Double pointer is the problem. The code should be:
void read_record(struct X* a,int size){ // Check the change
for (int i=0;i<size;i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container=(struct X*)malloc(sizeof(struct X)*n);
read_record(container,n); // Check the change
}

How to get struct field having pointer to the struct?

I have two structs:
struct first
{
int* array;
}
struct second
{
struct first* firsts;
} *SECOND;
Let's say somewhere I can get the address of one of struct first from SECOND->firsts by its index.
How could I get array of this struct? I've tried
SECOND->firsts[index]->array
but there is expression must have pointer-to-struct-or-union type error.
No malloc checks and no free - just to show the idea
struct first {
int* array; };
struct second {
struct first* firsts; } *SECOND;
#define NUMFIRSTS 50
#define ARRSIZE 50
int main() {
SECOND = malloc(sizeof(*SECOND));
SECOND -> firsts = malloc(NUMFIRSTS * sizeof(*SECOND -> firsts));
for(int f = 0; f < NUMFIRSTS; f++)
{
SECOND -> firsts[f].array = malloc(ARRSIZE * sizeof(*SECOND -> firsts[f].array));
}
//access
SECOND -> firsts[5].array[10] = 23;
}
Here you are.
#include <stdio.h>
#include <stdlib.h>
struct first
{
int* array;
};
struct second
{
struct first* firsts;
} *SECOND;
int main(void)
{
size_t n = 10;
struct first f = { NULL };
SECOND = malloc( sizeof( *SECOND ) );
SECOND->firsts = &f;
SECOND->firsts->array = malloc( n * sizeof( int ) );
for ( size_t i = 0; i < n; i++ )
{
SECOND->firsts->array[i] = ( int )i;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", SECOND->firsts->array[i] );
}
putchar( '\n' );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", f.array[i] );
}
putchar( '\n' );
// ...
// free all allocated memory
return 0;
}
the program output is
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
Pay attention to that as the pointer SECOND contains pointer to struct first f that in turn contains pointer to array then the both objects points to the same memory pointed to by the pointer array.
The array index operator [] has an implicit pointer dereference. So this expression:
SECOND->firsts[index]
Has type struct first, not struct first *, which means you can't use the -> operator on it. You need to instead use the member selector operator .:
SECOND->firsts[index].array

Allocating an array of structures within an array of structures

How can I allocate with malloc and array of structures within and array of structures?
for expample:
struct car_t{
int price;
float kmsDriven;
};
struct garage_t{
int locationX;
int locationY;
struct car_t * car;
}
There's an array of garages, which every one of them has an array of cars.
You will have to use a loop:
#define N 42
#define M 17
struct garage_t *a = malloc(sizeof *a * N);
for (int i = 0; i < N; i++) {
a[i].car = malloc(sizeof (*a[i].car) * M);
}
Just allocate as usual, one by one.
int garage_num = 3, car_num = 5;
int i;
struct garage_t *garage;
garage = malloc(sizeof(struct garage_t) * garage_num);
for (i = 0; i < garage_num; i++) {
garage[i].car = malloc(sizeof(struct car_t) * car_num);
}
You should check if malloc()s are successful for actual use.

write a code for the following function using struct pointers and array

I am new to C programming. Can any body tell me how can I do the coding for the term in bold?
create a structure called arrayData that contains an integer pointer called array and an integer variable called size.
create a function with the following header: arrayData* createArray(int size). Inside this function you will malloc space for a new arrayData structure. You will then need to create an array using the input variable as the number of elements. Finally you will need to set the variables in the malloc'ed arrayData pointer equal to the array and the array size. Finally return the pointer of malloc'ed arrayData structure.
I have tried something like:
#include<stdio.h>
struct arrayData
{
int *array;
int size;
}
struct arrayData* createArray(int size)
{
struct arrayData *str = (struct arrayData*)malloc(sizeof(struct arrayData));
int a = 10;
int arr[a];
for ( a = 0; a < 10; a++ )
{
str->arr[i] = a;
}
return str;
}
int arr[a]; is allocated locally inside the function and will be destroyed when the function returns. You should dynamically allocate str->array for proper allocation.
struct arrayData* createArray(int size)
{
struct arrayData *str = malloc(sizeof(struct arrayData));
int a = 10;
str->array = malloc(size * sizeof(int));
str->size = size;
for ( a = 0; a < 10; a++ )
{
str->array[i] = a;
}
return str;
}
Just a few changes for allocating size and array
struct arrayData* createArray(int size)
{
struct arrayData *str = (struct arrayData*)malloc(sizeof(struct arrayData));
int a = 10;
//int arr[size]; // array should be of size provided
int *arr = (int*)malloc(size * sizeof(int));
str->size = size; // you should assign size to structure variable
for ( a = 0; a < 10; a++ )
{
arr[i] = a;
}
str->array = arr; // you should point the array in structure to the
// integer arr which you created
return str;
}

Resources