4

I have the following simple source

#include <iostream>

int main() {
    int nv;
    nv = 3;
    int arr[nv] = { 0, 2, 5 };
    return 0;
}

When compiling with GCC on system 1 I get

error: variable-sized object ‘arr’ may not be initialized.

When compiling with GCC on system 2 I get no errors.

Compilation flags are the same in both cases, see below.

What is the reason for this, and how can I get my code to compile in system 1? I suspected it was related to gcc version, but I found no information to support this suspicion.

In system 1:

$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
...
$ make
g++ -MMD -g -g3 -Wall -Wunused -Wuninitialized -Wextra -fmessage-length=0 -std=gnu++11 -c -o obj/arrays_test.o src/arrays_test.cc
...

In system 2:

$ g++ --version
g++ (Ubuntu 5.5.0-12ubuntu1~16.04) 5.5.0 20171010
...
$ make
g++ -MMD -g -g3 -Wall -Wunused -Wuninitialized -Wextra -fmessage-length=0 -std=gnu++11 -c -o obj/arrays_test.o src/arrays_test.cc
...
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 1
    I added the g+ tag to help focus the question. It's really more about what changed in GCC than about standard C++. – StoryTeller - Unslander Monica Sep 17 '18 at 08:44
  • Just wondering: is this truly a minimal example? I.e. the `if (true)` is necessary? I can speculate about the problem - does the compiler _know_ that `nv==3` at runtime when the line `int arr[nv] = { 0, 2, 5 };` will execute? – MSalters Sep 17 '18 at 08:47
  • @MSalters - 1) Removing the `if (true)` does not remove the error. 2) It is a truly minimal example for what I need. – sancho.s ReinstateMonicaCellio Sep 17 '18 at 09:03
  • Can you post the big picture? Because right now, I'd say, simply go with `int arr[] = { 0, 2, 5 };`. Or use an STL container. Otherwise, why are you telling it it's size with some variable and then use a list initialization anyway? One thing you could do, if you really have to, is to populate the array with a loop instead. But sounds more like a XY-problem. – Aziuth Sep 17 '18 at 09:08
  • 1
    Not using poorly specified gcc extensions is a good first step to ensure portability of your code. Also avoid outdated gcc versions. – n. m. could be an AI Sep 17 '18 at 09:10
  • I would just use `constexpr` (if you have c++11). But I guess you just ask out for curiosity for research purpose. I don't think there is any good answer to your question, though. VLA support is not in C++ standard. – pptaszni Sep 17 '18 at 09:14
  • 2
    @VTT OP is explicitly using a gcc extension with `-std=gnu++11`. The *argumentum ad standartum* does not apply. – n. m. could be an AI Sep 17 '18 at 09:16
  • @n.m. For me it seems that op was unaware that VLA is a compiler extension. – user7860670 Sep 17 '18 at 09:25
  • @VTT from OP's comment in a deleted answer it seems that they are aware of that. – n. m. could be an AI Sep 17 '18 at 09:29
  • @VTT - I am aware VLA is non-standard, I did not find detailed info on gcc versions as to VLA. Perhaps with the help of comments posted I may be more on-target with such search (even if there were no comments which were specific regarding gcc versions and VLA). – sancho.s ReinstateMonicaCellio Sep 17 '18 at 09:40
  • @Aziuth - The big picture: the snippet posted means to be a MCVE of my case. Actual code is part of a large project with several developers, so if I am to suggest changing coding style/criteria, I should have as strong a basis for it as possible. In the actual case, the statement is `nv = `. I have to check if all similar occurrences in the code could be replaced by `int arr[] = { 0, 2, 5 };` (or analogous). – sancho.s ReinstateMonicaCellio Sep 17 '18 at 09:46
  • Yes but if nv can have another value than 3, how can you so certainly assign that list to it? The compiler not liking it sounds to be something desirable in my opinion. – Aziuth Sep 17 '18 at 10:00
  • @sancho.s: Since `if(true)` is unnecessary to reproduce the GCC 4.8 error, it follows that the example is not minimal. These things matter - if the branch would have been critical, you'd need to check specifically that part of the compiler, but since it's irrelevant we know that part of the compiler can be ignored. – MSalters Sep 17 '18 at 10:33
  • 1
    Narrowing it down: GCC 4.9.2 (Debian 4.9.2-10) behaves like GCC 5.5 (no error) – MSalters Sep 17 '18 at 10:36
  • @MSalters - Agreed as to `if`. Already removed it. – sancho.s ReinstateMonicaCellio Sep 17 '18 at 10:43

1 Answers1

2

The problem here is that you're using not one but two extensions.

The first extension, as noted already, is that you're using C99 VLA's in C++. That's a documented GCC extension.

The second extension is that even C99 doesn't allow initializers for VLA's :

C99 §6.7.8 [Initialization]

The type of the entity to be initialized shall be an array of unknown size or an object type that is not a variable length array type.

(In C11 you'll find this restriction in §6.7.9). But as the linked GCC page shows, this is not an official Gnu extension. The C99 restriction still stands. You'll need to use assignment instead of initialization.

MSalters
  • 173,980
  • 10
  • 155
  • 350