I have a main program that is supposed to receive as result of calling a function to load data (array of structs, undefined size), the proper data and then continuing processing it.
Following is a little example of what I'm trying to do. The function loadData
receives a pointer to the main pointer, so that the main pointer may be assigned a portion of memory through malloc
. The data is loaded and printed within the loadData
function. But when it returns to main it only shows a correct content for the first item of the array of structures. The second item is garbage.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int dni;
char cat;
int weight;
} boxers;
void loadData(boxers *(*xbox), int *xcount)
{
printf("How many boxers? ");
scanf("%d", xcount);
*xbox = (boxers *) malloc(sizeof(boxers) * (*xcount));
for (int i = 0; i < (*xcount); i )
{
printf("Provide the DNI for boxer number %d: ", i);
scanf("%d", &xbox[i]->dni);
printf("Provide the Category for boxer number %d: ", i);
scanf(" %c", &xbox[i]->cat);
printf("Provide the Weight for boxer number %d: ", i);
scanf("%d", &xbox[i]->weight);
}
// First print the result of data loading
for (int i = 0; i < *xcount; i )
{
printf("DNI for boxer number %d, is: %d \n", i, xbox[i]->dni);
printf("Category for boxer number %d, is: %c \n", i, xbox[i]->cat);
printf("Weight for boxer number %d, is: %d \n", i, xbox[i]->weight);
}
}
int main()
{
boxers *box;
int count;
loadData(&box, &count);
// Second print the result of data loading
printf("\n\n");
for (int i = 0; i < count; i )
{
printf("DNI for boxer number %d, is: %d \n", i, box[i].dni);
printf("Category for boxer number %d, is: %c \n", i, box[i].cat);
printf("Weight for boxer number %d, is: %d \n", i, box[i].weight);
}
free(box);
return 0;
}
The console output is the following:
How many boxers? 2
Provide the DNI for boxer number 0: 123
Provide the Category for boxer number 0: A
Provide the Weight for boxer number 0: 45
Provide the DNI for boxer number 1: 789
Provide the Category for boxer number 1: B
Provide the Weight for boxer number 1: 56
DNI for boxer number 0, is: 123
Category for boxer number 0, is: A
Weight for boxer number 0, is: 45
DNI for boxer number 1, is: 789
Category for boxer number 1, is: B
Weight for boxer number 1, is: 56
DNI for boxer number 0, is: 123
Category for boxer number 0, is: A
Weight for boxer number 0, is: 45
DNI for boxer number 1, is: 7471203
Category for boxer number 1, is: x
Weight for boxer number 1, is: 7536756
CodePudding user response:
&xbox[i]->dni
is wrong. The return value from malloc
was assigned to *xbox
, so *xbox
points to the memory, and xbox
points to that that pointer.
So the memory is at *xbox
. The first structure there is **xbox
or, equivalently, (*xbox)[0]
. The next structure is (*xbox)[1]
, and so on. So you want (*xbox)[i]
for the structure with index i
. Then, since that is a structure, not a pointer to it, you want .dni
, not ->dni
. So that member is (*xbox)[i].dni
. Then its address is &(*xbox)[i].dni
.
In contrast, since xbox
is a pointer to a pointer, then xbox[0]
is that pointer, and xbox[1]
would be the pointer after that. But there is no pointer after that; xbox
just points to a single pointer. So xbox[i]
is wrong.
The same change is needed in the other member references in the routine.
To avoid this easy-to-make mistake, in routines where a pointer-to-a-pointer is passed, a local pointer may be defined to make references easier:
void loadData(boxers **xbox, int *xcount)
{
…
boxers *p = *xbox = malloc(xcount * sizeof *p);
…
scanf("%d", &p[i]->dni);
…
}
CodePudding user response:
These assignments
for (int i = 0; i < (*xcount); i )
{
printf("Provide the DNI for boxer number %d: ", i);
scanf("%d", &xbox[i]->dni);
printf("Provide the Category for boxer number %d: ", i);
scanf(" %c", &xbox[i]->cat);
printf("Provide the Weight for boxer number %d: ", i);
scanf("%d", &xbox[i]->weight);
}
are incorrect. You have to write
for (int i = 0; i < (*xcount); i )
{
printf("Provide the DNI for boxer number %d: ", i);
scanf("%d", &( *xbox )[i].dni);
printf("Provide the Category for boxer number %d: ", i);
scanf(" %c", &( *xbox )[i].cat);
printf("Provide the Weight for boxer number %d: ", i);
scanf("%d", &( *xbox )[i].weight);
}
and then
for (int i = 0; i < *xcount; i )
{
printf("DNI for boxer number %d, is: %d \n", i, ( *xbox )[i].dni);
printf("Category for boxer number %d, is: %c \n", i, ( *xbox )[i].cat);
printf("Weight for boxer number %d, is: %d \n", i, ( *xbox )[i].weight);
}
Compare the above loop with this loop in main
for (int i = 0; i < count; i )
{
printf("DNI for boxer number %d, is: %d \n", i, box[i].dni);
printf("Category for boxer number %d, is: %c \n", i, box[i].cat);
printf("Weight for boxer number %d, is: %d \n", i, box[i].weight);
}
The difference is that in main the pointer box
has the type boxers *
while in the function the pointer xbox
has the type boxers **
. So you need at first to dereference the pointer in the function like ( *xbox )
and then to apply the subscript operator as you are doing in main as for example ( *xbox )[i].weight