1

I get this error when I run my code:

error: invariably modified 'Square_Toys' at file scope.

There is a variable defined globally at the top of my code called NumOfToys, and then I define my array Toy* Square_Toys[NumOfToys] following it after. The NumOfToys is dependent on what the user inputs, so I cannot define the size of the array beforehand :(

How I can get rid of this error?

int NumOfToys; // <------- This is entered through the user running the programin the terminal
struct toy * Square_Toys[NumOfToys];
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Masterminder
  • 1,127
  • 7
  • 21
  • 31

3 Answers3

2

You can't use a direct array in that case. Variable Length Arrays can only be declared in local scope. I.e. if the array size is a run-time value, then you cannot declare such array in file scope. All arrays with static storage duration shall have compile-time sizes. There's no way around it.

If your array has to declared in file scope (BTW, why?), you have to use a pointer instead and allocate memory manually using malloc, as in

int NumOfToys;
struct toy **Square_Toys;

int main()
{
  ...
  /* When the value of `NumOfToys` is already known */
  Square_Toys = malloc(NumOfToys * sizeof *Square_Toys);
  ...
  /* When you no longer need it */
  free(Square_Toys);
  ...
}

Another alternative would be to stop trying to use a file scope variable and switch to a local array instead. If the array size is not prohibitively large, you will be able to use Variable Length Array in local scope.

A third alternative would be an ugly hybrid approach: declare a global pointer, but use a local VLA to allocate the memory

int NumOfToys;
struct toy **Square_Toys;

int main()
{
  ...
  /* When the value of `NumOfToys` is already known */
  struct toy *Local_Square_Toys[NumOfToys];
  Square_Toys = Local_Square_Toys;
  ...
}

But this is here just for illustrative purposes. It is ugly.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • If I put this in my main function, and I have functions above it that call it, I would get a compiler error thats it's not defined correct? Do you know how I can make it so it can be accessed by the other functions, without physically passing it into the functions? – Masterminder Oct 06 '13 at 17:20
  • I just want to allocate an array of those toys which will be accessed later on by other functions – Masterminder Oct 06 '13 at 17:21
  • @Masterminder: That is true. That means you will have to *pass* it to those other functions as an argument. This is the proper way to do it. Global variable might seem "easier", but it is really a very poor and lazy way out. – AnT stands with Russia Oct 06 '13 at 17:22
  • 1
    @Masterminder: If you want to allocate an array of toys, why does the code sample in your question declare an array of *pointers* to toys? – AnT stands with Russia Oct 06 '13 at 17:23
  • I am declaring an array of pointers to toys, and then later on will allocate memory for each toy – Masterminder Oct 06 '13 at 17:24
  • @Masterminder: That's OK. If you want to do it that way, there's nothing wrong in it. I just wanted to make sure I understood your intent correctly. So, my answer stands. Choose whatever approach you prefer. – AnT stands with Russia Oct 06 '13 at 17:25
  • So if I define it in my main function and allocate memory for it, there is no way I can access it in my other function? What if I declare it globally in my code? – Masterminder Oct 06 '13 at 17:27
  • @Masterminder: You can't declare something globally and then define it locally. You are basically limited to three alternatives from my answer. Again, the best approach is the one that does not use any global variables at all. Declare everything locally and pass it around using function parameters. That's how it is normally done in C. – AnT stands with Russia Oct 06 '13 at 17:31
0

Size of global array should be constant because the compiler needs to know it in compile time. If you need a dynamic array, allocate it with malloc in runtime:

Toy **Square_Toys;

void foo(void) {
  Square_Toys = malloc(NumOfToys * sizeof(Toy*));

  // do stuff here

  free(Square_Toys);
}
simon
  • 1,210
  • 12
  • 26
  • `sizeof(Toy)` -> `sizeof SquareToys[0]`. In case the type ever changes. –  Oct 06 '13 at 17:15
  • If I do it like this in my main function and allocate the memory, but I have functions above the main that call it, it would give me an error that Square_Toys is not defined, correct? – Masterminder Oct 06 '13 at 17:17
  • The OP code sample requests an *array of pointers* to `Toy`, not an array of `Toy`. – AnT stands with Russia Oct 06 '13 at 17:19
  • No, you won't get 'Square_Toys not defined' error, but you should allocate the array before you use it. I have updated the code according to the new code snippet in the question. – simon Oct 06 '13 at 17:21
0

The NumOfToys is dependent on what the user inputs so I cannot define the size of the array beforehand

Either You can dynamically allocate space for array or use VLA's. For VLA, after user input for NumOfToys declare your array in main.

printf("Enter number of toys: ");
scanf("%d", &NumOfToys);

struct toy * Square_Toys[NumOfToys];    
haccks
  • 104,019
  • 25
  • 176
  • 264