ccode-composer

"Variable may not be initialized" when specifying the array size with another variable


I am trying to compile the following code:

    int rows = 4;
    int columns = 4;
    int numblock[columns][rows] = {
                                   {0,0,0,0},
                                   {0,0,0,0},
                                   {0,0,0,0},
                                   {0,0,0,0}
    };

And it tells me that the variable may not be initialized. When I write int numblock[4][4] instead, the compiler doesn't complain.

I guess it is related to this: C compile error: "Variable-sized object may not be initialized"

Can someone please explain this to me?

Edit - from a comment by op:

.. I set columns and rows = 4. It should know the size, shouldn't it?


Solution

  • The answer is already in the link you provide but I'll try to clarify as the linked answer wasn't clear to you.

    First - what you have is called VLA, i.e. a Variable Length Array. The idea is simply that you can use another variable to set the size of the array. So this allows the size to be set at run time.

    The problem you have is because: It is not allowed to initialize a VLA

    It is as simple as that - it is just not supported in C.

    It works fine with the initializer when the array is defined with numbers (e.g. [4][4]). That is because the size of the array is known at compile time

    The fact you you initialize rows and columns to 4 makes no difference. The compiler do not track whether these variables are changed before the array is created. For instance like this:

    void foo()
    {
        int rows = 4;
        int columns = 4;
        rows = rows + 42;   // or scanf("%d", &rows) to get the number of rows from a user
        int numblock[columns][rows];  // no - initializer here - not allowed
    }
    

    Even if you make rows and columns constants - like const int rows = 4; - it still won't work in C (but in C++ it will).

    One way to "initialize" a VLA is to use memset - like:

    void foo()
    {
        int rows = 4;
        int columns = 4;
        int numblock[columns][rows];           // no - initializer here - not allowed
        memset(numblock, 0, sizeof numblock);  // but using memset is easy
    }
    

    If you want a fixed number of rows/columns the C way is to use defines. Like:

    #define ROWS 4
    #define COLUMNS 4
    
    void foo()
    {
        int numblock[ROWS][COLUMNS] = {
                                       {0,0,0,0},
                                       {0,0,0,0},
                                       {0,0,0,0},
                                       {0,0,0,0}
                                      };
    }
    

    This will work because defines are resolved at compile time