3

I get a compile error when I try to assign the struct with the array size of a global variable which the user will input in at the command line, and then pass the value back to the variable that was declared globally.

Here is just sample code:

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

int Type;

struct list_el {
    int val;
} list1[Type];

struct list_el item;

int main() {
    Type = 10; // Just a sample
}

Error:

variable modified at file scope Struct C

Is there a way to fix the problem? I need it to work globally.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pakaphol Buathon
  • 188
  • 3
  • 18

4 Answers4

4

When declaring an array, you need a compile-time constant for the size, which Type isn't.

If you want to allocate during runtime, use pointers and malloc.


Well, actually you can have non-constant variables for array size, it's called variable-length arrays. The problem with using a global variable for the size is that global variables are initialized to zero, so what you are doing is actually creating an array with zero elements, but only if the variable Type is initialized before the array is created.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

Your code is not valid: you can't first declare an array using a variable as the size, and then assign to the variable.

Or, you can, but the array certainly won't magically change.

Also, it's very strange to have the variable and array be global.

You should probably just do:

int main(void)
{
  int num;

  printf("enter size:\n");
  if(scanf("%d", &num) == 1 && num > 0)
  {
    struct list_el list1[num];

    /* here, work with the array. */
  }
}

Note that using a variable like this is a C99 feature.

unwind
  • 391,730
  • 64
  • 469
  • 606
2

If you want both the list and its magnitude Type to be global and dynamically allocated, you need to do just that: dynamically allocate.

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

int Type;

struct list_el {
    int val;
} *list;

int main() 
{
    Type = 10;

    list = malloc(Type * sizeof(*list));

}

That said, seriously question whether you need these globally. If your compiler supports it you can use a local variable-length array (VLA). It is a C99 optional feature, testable by checking if __STDC_NO_VLA__ is not defined.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • So this code will assign Type vaiable (10) to size of struct list_e1 array to 10 and be able to accessed that array globally – Pakaphol Buathon Oct 17 '13 at 08:26
  • @user1611864 this will allocate enough memory for `Type` number of `struct list_el` elements, assigning the resulting memory address to the pointer `list`, which can then be used as `list[n]` for all `n` between 0 and the value of `Type-1` at the time of the allocation. This does NOT magically grow or shrink the allocated buffer size just by changing `Type` later on. If you want that, see, and understand [`realloc()`](http://en.cppreference.com/w/c/memory/realloc). – WhozCraig Oct 17 '13 at 08:29
  • @user1611864 ...and it doesn't have to be global. You can make your "other functions" take a pointer and size as parameters. I don't advise doing this globally, but if you're set on doing so, this is one way. – WhozCraig Oct 17 '13 at 08:31
  • For the `__STDC_NO_VLA__` you are not exactly right. This is a *mandatory* feature for C99 which became optional with C11. So compilers that implement this feature test macro are probably not yet very common. – Jens Gustedt Oct 17 '13 at 09:23
  • @JensGustedt C99 6.10.8.3 Conditional feature macros, " \_\_STDC_NO_VLA__ The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types". Or was that just left in the standard by mistake? – WhozCraig Oct 17 '13 at 14:39
  • C99 (n1256) has no section 6.10.8.3, but C11 (n1570) has. You are reading the wrong document :) – Jens Gustedt Oct 17 '13 at 15:35
  • @JensGustedt Seriously? I had no idea. The "ISO/IEC 9899:201x" in the document title tossed me. I really need to stop reading drafts and just fork over for the official copy (mine was 1548, btw, but I also have 1570, and likewise its obviously in there as well, as you pointed out. thanks for the info). – WhozCraig Oct 17 '13 at 16:48
0

You could use alloca() in main to stack-allocate the memory.

struct list_el {
  int n;
} *list;
static int Type;

int main(int argc, char** argv) {
  Type = argc;
  list = alloca(sizeof(struct list_el) * Type);

  // use list...
}

The memory will stay in-scope until main() returns. I don't know what happens in an atexit() callback. That's an interesting question.

Marc O'Morain
  • 3,699
  • 5
  • 28
  • 34