0

Why I can't allocate memory for array x.a this way? Compiler says that x.a is not initialized in main, but I want to initialize array in function fun. In this function, I want to make the memory for the first element and put it in the array, make the memory for second and put it in the array etc. What should I change in this code?

#include <stdio.h>
#include <stdlib.h> 

typedef struct {
  int *a;

} array;

void fun(int *a,int num)
{
  int i;

  for(i=0;i<num;i++)
  {
    a=(int*)realloc(a,(i+1)*sizeof(int));
    scanf("%d",(a+i));
  }
}
int main(int argc,char *argv[]) 
{
  array x;
  int i,num;

  scanf("%d",&num); //number of elements in array *a (in struct)

  fun(x.a,num);

  for(i=0;i<num;i++)
   printf("%2d",x.a[i]); //prints elements
}
6
  • Why not just allocate the whole space outside the loop? Commented Jul 9, 2018 at 23:50
  • x.a is passed to fun by value, so fun gets a copy of the pointer and the original one isn't modified. I don't know how you would fix this in C though since I code in C++. Also, realloc() has to copy the existing block of memory to a new location every single time (the reason it's called realloc), so it's more efficient to allocate all the memory at once instead of repeatedly expanding a block of memory. Commented Jul 9, 2018 at 23:53
  • You have to set x.a to something before you can use it. The memory for x is there because that's a local variable... But x.a is a pointer to the unknown when you go to use it the first time in main. Commented Jul 9, 2018 at 23:54
  • @ScottHunter That would be the best solution, but I'm a beginner programmer and I want to practice and looking for the other solutions to one problem. Commented Jul 10, 2018 at 0:02
  • @gaga Not sure finding bad solutions is a good thing to practice, but to each his/her own. Commented Jul 10, 2018 at 0:06

2 Answers 2

3

Just as you need to pass the address of num to have scanf assign to it, you'd need to pass the address of x.a (and change the type of the matching parameter accordingly, and the use of a inside of fun) in order to assign to it from inside fun.

Sign up to request clarification or add additional context in comments.

1 Comment

Or you can return the new value.
2

You have two problems. The first is that x.a is not set to a value before it is used. You define x at the start of main:

array x;

That creates x but does not put anything in it. Then you pass x.a to fun in:

fun(x.a,num);

This says to pass the value of x.a to fun. But x.a does not have a value yet, so that is wrong. (By the way, make your code readable. Put spaces after commas and semicolons, the same as in normal English text.)

Then, in fun, you use a in:

a=(int*)realloc(a,(i+1)*sizeof(int));

The first time that is executed, a does not have a proper value because it was passed the value from x.a, which was never set. realloc is for reallocating existing allocations. You have to pass it an initialized pointer value. (That includes NULL; you are allowed to pass it NULL to say you want to perform an initial allocation instead of a reallocation.)

The easiest way to fix these problems is to give x.a an initial value, which you can do by changing the definition of x to:

array x = { NULL };

The second problem is that fun never passes an updated value back to its caller. Your declaration of fun is:

void fun(int *a,int num)

This says that fun accepts a value that is a pointer to an int. When fun is called with:

fun(x.a,num);

only the value of x.a is passed. The actual object x.a is not passed, just its value. So fun has no way to return a new value for x.a. There are two ways to fix this. One is to change fun to accept a pointer to x.a:

void fun(int **a,int num)

and change the main routine to pass the address of x.a:

fun(&x.a,num)

and change every use of a inside fun to *a:

*a=(int*)realloc(*a,(i+1)*sizeof(int));
scanf("%d",(*a+i));

The other way is to return the new pointer as the return value of fun. Change the declaration of fun to:

int *fun(int *a,int num)

and change main to update x.a when fun returns it:

x.a = fun(x.a,num);

and change fun to return the value (do not change a to *a as above) by inserting this statement at the end:

return a;

Once that is done, your program will be largely working, but there are two more issues you ought to address:

  • It is wasteful to realloc repeatedly when you already know the final size you want. You ought to just allocate memory once for the size you want. realloc is for when the size you need changes.
  • realloc can fail. You should modify the code to handle the case when it fails and returns NULL.

1 Comment

That was really useful. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.