Variably modified array at file scope in C

I have some code like this:

static int a = 6; static int b = 3; static int Hello[a][b] = { { 1,2,3}, { 1,2,3}, { 1,2,3}, { 1,2,3}, { 1,2,3}, { 1,2,3} }; 

But when I compile it, it says error:

variably modified 'Hello' at file scope

How could this happen? And how could I fix it?

7

4 Answers

You can not have a static array whose size is given as a variable.

That's why constants should be #defined:

#define a 6 

This way, the preprocessor will replace a with 6, making it a valid declaration.

3

Simple answer: A variable modified array at file scope is not possible.

Detailed:

Make it a compile time integral constant expression, since the array length must be specified at the compile time.

Like this:

#define a 6 #define b 3 

Or, follow the C99 standard. and compile like for GCC.

gcc -Wall -std=c99 test.c -o test.out

The problem here is a variable-length array with providing length may not be initialized, so you are getting this error.

Simply

static int a = 6; static int b = 3; void any_func() { int Hello [a][b]; // No need of initialization. No static array means no file scope. } 

Now use a for loop or any loop to fill the array.

For more information, just a demo:

#include <stdio.h> static int a = 6; int main() { int Hello[a] = {1, 2, 3, 4, 5, 6}; // See here initialization of the array 'Hello'. It's in the function // Scope, but still an error return 0; } 

Compile

cd ~/c clang -std=c99 vararr.c -o vararr 

Output:

vararr.c:8:11: error: variable-sized object may not be initialized int Hello[a]={1,2,3,4,5,6}; ^ 1 error generated. 

If you remove static and provide initialization then it will generate the error as above.

But if you keep static as well as initialization then it will still be an error.

But if you remove the initialization and keep static, the below error will come.

error: variable length array declaration not allowed at file scope static int Hello[a]; ^ ~ 1 error generated. 

So a variable-length array declaration is not allowed at file scope, so make it function or block scope inside any function (but remember making it function scope must remove initialization)

Note: Since it's C tagged, making a and b as const won't help you, but in C++ const will work fine.

12

When using Clang/LLVM, the following works:

static const int a = 6; static const int b = 3; static int Hello[a][b] = { {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3} }; 

(To see it in the generated assembly, one needs to use 'Hello', so it will not be optimized out.)

However, this will generate an error if C99 mode is selected (-std=c99). It will only generate a warning (Wgnu-folding-constant) if -pedantic is selected.

=== EDIT === Clang now (version 14.0.0) generates this warning as default: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]

GCC does not seem to allow this (const is interpreted as read-only).

See the explanation in this question:

"Initializer element is not constant" error for no reason in Linux GCC, compiling C

5

The dimensions of the array must be constant expressions and your friend 'compiler' must be informed about that. So tell to compiler that a and b are constant values.

static constexpr int a = 6; static constexpr int b = 3; static int Hello[a][b] = { { 1,2,3 }, { 1,2,3 }, { 1,2,3 }, { 1,2,3 }, { 1,2,3 }, { 1,2,3 } }; 
1

ncG1vNJzZmirpJawrLvVnqmfpJ%2Bse6S7zGiorp2jqbawutJoaGxuZGqGdIKOr5iroZGXubp5zKibop6ZmrFurdGrmLJlkal6p7XLnmSsm5%2Blsm61zWaa