5

The following program compiles as a C program:

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

void f(int n, int m, int x[n][m]) {
  printf("x[0][2] = %i\n",x[0][2]);
}

int main() {
  int v[][3] = { {0,1,2}, {3,4,5} };

  f(2,3,v);
}

However, when compiled as C++ with g++, I have:

main.c:4:29: error: use of parameter outside function body before ‘]’ token
 void f(int n, int m, int x[n][m]) {
                             ^

It seems that this feature of C does not exist in C++. Is there any flag that can be given to g++ so that it accepts the code?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Bérenger
  • 2,678
  • 2
  • 21
  • 42
  • 10
    C++ does not support variable-length arrays – user438383 Dec 09 '22 at 13:57
  • 2
    C and C++ are two different languages. You either compile C code or C++ code. – NathanOliver Dec 09 '22 at 13:57
  • @πάνταῥεῖ Not sure the dupe works here. This isn't a VLA issue – NathanOliver Dec 09 '22 at 13:59
  • Yes, @NathanOliver this has nothing to do with VLA – Bérenger Dec 09 '22 at 14:00
  • 1
    No, there is no flag to use a mix of C and C++ ... you could look at extern C, like https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c but if you want C++ maybe use a `std::vector`? – doctorlove Dec 09 '22 at 14:02
  • @user438383: If by “C++”, you mean the C++ of the C++ standard, this question does not ask whether C++ “supports” variable-length arrays. The C++ standard allows extensions, and, even if it does not, compilers may support C++ variants other than standard C++. This question asks whether g++ supports an extension or variant suitable to the code in the question. – Eric Postpischil Dec 09 '22 at 14:03
  • 1
    @ThomasWeller no it does not. Read the question carefully. As a matter of fact gcc does have VLAs as extension (be they standard or not, it works) but nevertheless gcc does not compile this code – 463035818_is_not_an_ai Dec 09 '22 at 14:12
  • Could you please add the exact command line you used to compile it? – Bob__ Dec 09 '22 at 14:15
  • In C++, with template, you might do`template void f(/*const*/ int (&x)[N][M])`. – Jarod42 Dec 09 '22 at 14:17
  • This is not the first time g++ did something unexpected with the (supposed) support for VLA's. There are older versions of g++ that refused to compile code that used VLA's in STL algorithm functions, for example `int n = 10; int a[n]; std::sort(a, a + n);`. Some weird compiler error would show up. – PaulMcKenzie Dec 09 '22 at 14:20
  • 1
    GCC will accept `void f(int n, int m, int (*x)[])`, and, in C, you could then complete the type inside the function with `int (*a)[m] = x;`, but GCC objects to the conversion. – Eric Postpischil Dec 09 '22 at 14:32
  • @EricPostpischil The answer I linked already provides a similar but working workaround. – Nelfeal Dec 09 '22 at 14:35
  • https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51352. Note there is a world of difference between "C++" and "g++". Please make the question title reflect what is actually being asked. – n. m. could be an AI Dec 09 '22 at 15:29

1 Answers1

2

It seems that this feature of C does not exist in C++.

Correct.

Is there any flag that can be given to g++ so that it accepts the code?

No, there is no such feature allowing a VLA as part of a parameter list. You will have to compile the code as C.

Other similar gcc extensions exist, see: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Actually I have no idea why gcc documentation claims that VLA can be used as parameters when it refuses to compile them even in lax mode. Smelly documentation? – Lundin Dec 09 '22 at 14:16
  • 1
    from the docs you link: "You can also use variable-length arrays as arguments to functions: " and then follows an example not too different from OPs – 463035818_is_not_an_ai Dec 09 '22 at 14:17
  • [See also](https://stackoverflow.com/questions/25551779/intnm-where-n-and-m-are-known-at-runtime), the answer says that there seems to be a bug and even provides a workaround. Though it's from 2014... – Nelfeal Dec 09 '22 at 14:17
  • @463035818_is_not_a_number Yes but it refuses to compile such in g++. But you can compile `int n=5; int array[n];` with g++, as long as compiling in lax non-standard mode. – Lundin Dec 09 '22 at 14:18
  • and I always thought using them as parameter is the actual motivation to have VLAs – 463035818_is_not_an_ai Dec 09 '22 at 14:19
  • 1
    @463035818_is_not_a_number It is. gcc isn't making any sense. – Lundin Dec 09 '22 at 14:19
  • 1
    Though please note that the linked doc is for C, C90 and C++ all in one. Because... gcc quality documentation. – Lundin Dec 09 '22 at 14:21
  • looks like a bug then. I suggest to change the phrasing, because according to what you link it isnt actually "Other similar" – 463035818_is_not_an_ai Dec 09 '22 at 14:22
  • @Lundin: I do not see that the GCC documentation says variable-length arrays can be used as parameters in C++. [This page](https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Variable-Length.html#Variable-Length) for variable-length arrays is about C extensions. The [section on C++](https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/C_002b_002b-Extensions.html#C_002b_002b-Extensions) does not have subsection about variable-length arrays. It has a general statement that “most of the C language extensions” can be used in C++ but does not say variable-length arrays can… – Eric Postpischil Dec 09 '22 at 14:23
  • … Where did you see documentation saying variable-length arrays can be used as parameters in C++? – Eric Postpischil Dec 09 '22 at 14:23
  • @EricPostpischil link in the question: "You can also use variable-length arrays as arguments to functions:" – 463035818_is_not_an_ai Dec 09 '22 at 14:23
  • @463035818_is_not_a_number: That page is in the “C extensions” section, not the C++ extensions section. – Eric Postpischil Dec 09 '22 at 14:24
  • @EricPostpischil and it says "... and as an extension GCC accepts them in C90 mode and in C++". Well, ok, i am already convinced. Lets agree that the documentation is not as clear as it could be – 463035818_is_not_an_ai Dec 09 '22 at 14:25
  • @463035818_is_not_a_number: Well, you can use variable-length arrays in C++ in GCC. But not as parameters, as least not freely (a pointer to a variable-length array is accepted). – Eric Postpischil Dec 09 '22 at 14:26
  • 1
    yes. The docs arent really wrong. They say you can use VLAs in C++, right. And they say you can use them as parameters, also right, just not in C++. – 463035818_is_not_an_ai Dec 09 '22 at 14:27
  • i mean who needs VLAs in c++ anyhow? I never understood why gcc default settings has them. The main effect is to confuse newbies :/ – 463035818_is_not_an_ai Dec 09 '22 at 14:29
  • 1
    Note there is a second issue here; the compiler is objecting to using a previous parameter in a declarator. It might be interesting to discuss the C++ rules about that. Even if GCC supported variable-length arrays in parameters, the parameter scope or lifetime might be an issue. – Eric Postpischil Dec 09 '22 at 14:29
  • Also, why isn't VLA mentioned in the _C++ extensions_ chapter... because they clearly do work if used as local variables. – Lundin Dec 09 '22 at 14:31
  • @463035818_is_not_a_number, afaik C++ has no good alternative for handling contiguous multidimensional arrays. VLA types suits very well for this purpose. – tstanisl Dec 09 '22 at 14:35
  • @tstanisl It does, it's called `std::vector`. If you need multiple dimensions then you wrap that 1d vector in a class to fake that it has multiple dimensions. – NathanOliver Dec 09 '22 at 14:36
  • @NathanOliver He said handling contiguous multidimensional arrays, not "handle a massive non-contiguous bloat on the heap". Stroupstrup kept feverishly insisting that there was no reason why std::vector wasn't as good as plain C arrays. Until they invented std::array, then he stopped. – Lundin Dec 09 '22 at 14:38
  • @NathanOliver, as I said. Flattening multidimensional array is not a **good alternative** to VLA types. – tstanisl Dec 09 '22 at 14:38
  • @Lundin How is `std::vector` a non-contiguous bloat? The only 2 advantages I see for VLAs are that they *might* go on the stack and that multi-dimensional ones are built-in (I wish there was a `std::multi_dimensional_vector` or something similar). But to be honest, if I want a variable-length array that goes on the stack, I would probably just use a fixed-sized array with maximum length instead, and use whatever portion I need. – Nelfeal Dec 09 '22 at 14:45
  • @Nelfeal, VLA can be on heap as well. Try `int (*arr)[cols] = calloc(rows, sizeof *arr);` – tstanisl Dec 09 '22 at 14:46
  • @tstanisl Yes I know, I said "might". But a VLA on the heap is basically a `std::vector`, and I prefer the latter. – Nelfeal Dec 09 '22 at 14:47
  • @Nelfeal, `std::vector` is intrinsically one-dimensional. `std::vector` is a really crappy non-contiguous data structure. Emulating multidimensional array as 1D is very error prone and really cumbersome. Upcoming `std::span` **may** be some alternative to VLAs but the lack the simplicity and they suffer from ABI issues. – tstanisl Dec 09 '22 at 14:49
  • @tstanisl nobody here was suggesting that nested vectors are a cool thing. Anyhow I think this is going a little offtopic... – 463035818_is_not_an_ai Dec 09 '22 at 14:51
  • @tstanisl Nobody mentioned `std::vector`. I'm not sure how emulating multidimensional array as 1D would be error prone if that was packaged in a (ideally standard) class. Also, `std::span` isn't upcoming, it's more than 2 years old. I really don't think VLAs have any place in C++. They kinda do in C, though they became optional in C11 (see `__STDC_NO_VLA__`), so you may not even be able to use them. – Nelfeal Dec 09 '22 at 14:56
  • VLA's are all fake anyway in C++. What stops the g++ authors from supporting anything related to VLA's and C++ code that seems to be "missing"? Maybe it's a "(C++) beggars can't be choosers" scenario. – PaulMcKenzie Dec 09 '22 at 14:56
  • @Nelfeal, VLA types **will** be mandatory in C23 – tstanisl Dec 09 '22 at 15:01
  • @tstanisl Pointers to them at least. – Lundin Dec 09 '22 at 15:02
  • 1
    Anyway, all these discussions are dragging _way_ off-topic. The topic here is VLA support as a g++ extension. – Lundin Dec 09 '22 at 15:02
  • @Lundin: Actually, the topic here is “use of parameter outside function body,” as the error message says. Variable-length arrays are what OP tried to do; the use of a parameter outside of the function body is what stopped them. – Eric Postpischil Dec 09 '22 at 15:51