7

I'm dynamically calculating the size of an array. Something like:

void foo(size_t limit)
{
  char buffer[limit * 14 + 1];
}

But just GCC compiler says:

error: ISO C90 forbids variable length array ‘buffer’

searching on SO I found this answer:

C99 §6.7.5.2:

If the size is an expression that is not an integer constant expression... ...each time it is evaluated it shall have a value greater than zero.

So, I did the re-declaration of size limit type variable to:

void foo(const size_t limit)

But it continues to give warning for me. Is this a GCC bug?

Community
  • 1
  • 1
Jack
  • 16,276
  • 55
  • 159
  • 284
  • 12
    Well, `C90 != C99`. – user7116 Apr 19 '12 at 18:19
  • 2
    Declaring `size_t limit` as `const` doesn't change anything. It's still a variable length array since the size is run-time determined. – Mysticial Apr 19 '12 at 18:19
  • GCC is telling you that with the command-line options you are using, it compiles with respect to the C90 standard by default. The paragraph you quote is from C99. This is the cause of your problem, not the type of `limit`. – Pascal Cuoq Apr 19 '12 at 18:20
  • It should be noted that GCC itself supports Variable Length Arrays as a language extension, so this would work if you were not compiling in c99 mode - but it's not portable unless you will always be using a compiler that has such an extension or implements C99's VLAs. – wkl Apr 19 '12 at 18:21
  • 1
    Just invoke gcc with `gcc -std=c99 -pedantic ...` – pmg Apr 19 '12 at 18:21

6 Answers6

15

const-qualifying a variable doesn't make it a compile-time constant (see C99 6.6 §6 for the defintion of an integer constant expression), and before the introduction of variable-length arrays with C99, array sizes needed to be compile-time constants.

It's rather obvious that const-qualify a variable doesn't make it a compile-time constant, in particular in case of function parameters which won't be initialized until the function is called.

I see the following solutions to your problem:

  • compile your code as C99 via -std=c99 or -std=gnu99
  • allocate your buffer via malloc()
  • use alloca() if available, which is the closest you can come to variable-length arrays with C90
  • choose a maximum buffer size which is always used and fail if the given limit argument overflows

As a side note, even though C99 allows variable-length arrays, it's still illegal to use the value of an integer variable with static storage duration as size for an array with static storage duration, regardless of const-qualification: While there's nothing which prevents this in principle if the integer variable is initialized in the same translation unit, you'd have to special-case variables with visible defintion from those whose definition resides in a different translation unit and would either have to disallow tentative defintions or require multiple compilation passes as the initialization value of a tentatively defined variable isn't known until the whole translation unit has been parsed.

Christoph
  • 164,997
  • 36
  • 182
  • 240
6

const does not introduce a constant in C but a read-only variable.

#define SIZE 16
char bla[SIZE];   // not a variable length array, SIZE is a constant

but

const int size = 16;
char bla[size];   // C99 variable length array, size is a constant
Ed Sabol
  • 433
  • 4
  • 15
ouah
  • 142,963
  • 15
  • 272
  • 331
3

C90 doesn't allow variable length arrays. However, you can use the c99-gcc compiler to make this work.

You are compiling with c90-gcc but looking at C99 specifications.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
P.P
  • 117,907
  • 20
  • 175
  • 238
2

No it is not a bug. You can't use a VLA in C90. When you declared

const size_t limit

that is not a constant expression. A constant expression would be something like a literal value 666.

Note that C differs significantly from C++ in this regard. Even a constant like this

const int i = 666;

is not a constant expression in C. This is the primary reason why constant values are typically declared with #define in C.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks alot for your explanation. out curiosity,why the C90 standard don't accept a constant expression like that I'm tried to use? because if I'm using const type, it mean than I can't modify it later,so,what is reason for forbid it? and C99 std,is otherwise,the int value don't need be at least of const type. sorry for my bad english. :) – Jack Apr 19 '12 at 19:02
  • 3
    @Jack You don't have a constant expression. You have a `const` variable. A constant expression would be 42 or 66. – David Heffernan Apr 19 '12 at 19:05
0

As written in your question, this is from C99, not C90, you need to compile it against C99 to be able to use variable length arrays.

MByD
  • 135,866
  • 28
  • 264
  • 277
  • 1
    Or you may be able to use [alloca](http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html) instead. – James M Apr 19 '12 at 18:20
  • Yup, yet dynamically allocating memory is something else. – MByD Apr 19 '12 at 18:21
  • Isn't alloca pretty much exactly the same as using a variable length array? (as it uses stack memory rather than the heap) – James M Apr 19 '12 at 18:22
0

A const qualified variable is not an integer constant expression in the sense of the standard. This has to be a literal constant, an enumeration constant, sizeof or some expression composed with these.

Switch to C99 if you may. The gcc option is -std=c99 (or gnu99 if you want gnu extension.)

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177