-1

I know that when I do this

int x;
cin >> x;
char arr [x];

it is ill fomed according to c++ standard since c++ does not allow static arrays of variable size.

My question is, if I declare static array in function scope with variable size from function parameter is it still ill formed? Or is it well defined in the standard?

void foo(int size)
{
    char arr [size];
    // do something
}

void main()
{
   foo(10);
   foo(20);
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
sfgr
  • 1
  • 1
  • 4
    why not `std::string` or `std::vector` ? – 463035818_is_not_an_ai Aug 28 '19 at 10:18
  • In your both examples the size of the array is variable - it's not going to work. – vahancho Aug 28 '19 at 10:19
  • you seem to be using a variable lenght array compiler extension, no this is not standard c++, whether inside a function or not – 463035818_is_not_an_ai Aug 28 '19 at 10:19
  • possible duplicate: https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard – 463035818_is_not_an_ai Aug 28 '19 at 10:20
  • _"... does not allow static arrays of variable size..."_ corrected: _"... does not allow arrays of variable size..."_ – Richard Critten Aug 28 '19 at 10:22
  • It is not a _static_ array, rather an _automatic_ one. And this is not a _declaration_, rather both a _declaration_ and _definition_. Declaration only would be `extern char arr[]`. – Maxim Egorushkin Aug 28 '19 at 10:27
  • Related: https://stackoverflow.com/q/32832705/1025391 – moooeeeep Aug 28 '19 at 10:30
  • It may seem like this could be valid because the value is hard-coded in the function calls (and thus "known" at compile time), but the source of the function's argument is irrelevant. – molbdnilo Aug 28 '19 at 10:48
  • In your first example, `arr` has automatic storage duration, not static (assuming all three lines are within a function block - since the first two lines would also not compile otherwise). Both examples involve a variable length array (VLA) and are therefore not valid C++ although, unfortunately, some C++ compilers support VLA's as a non-standard extension (e.g. because they are also C99 compilers). Also, in standard C++, `main()` returns `int`, not `void`. – Peter Aug 28 '19 at 11:38
  • @MaximEgorushkin - a definition IS a type of declaration. Not all declarations are definitions. – Peter Aug 28 '19 at 11:42

3 Answers3

3

For starters you have no "static arrays". The arrays used in your examples have automatic storage duration. And C where variable length arrays are allowed requires that such arrays had automatic storage duration.

Variable length arrays are not a standard feature of C++.

Instead use the standard container std::vector. Or if you are using strings then use the standard class std::string.

For example

#include <iostream>
#include <string>

void foo(int size)
{
    std::string s;
    s.resize( size );
}

int main()
{
   foo(10);
   foo(20);
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Using `std::string`or `std::vector` does not avoid heap allocation. When declaring array in function based on parameter It should be just simple subtract of that argument from stack pointer in function prolog, right? – sfgr Aug 28 '19 at 11:19
  • @sfgr The C++ Standard did not include this feature from C. – Vlad from Moscow Aug 28 '19 at 11:21
0

This is not a valid C++ code:

char arr [size];

It may work on some compilers which has support of variable size array of C as an extension.

The array also is not static it is automatic in your case if size was constant known at compile time.

It is not valid anywhere neither function scope nor anywhere else.

You can use std containers such as vector which has support for variable size or even std::string.

Oblivion
  • 7,176
  • 2
  • 14
  • 33
0

When foo is called, a new stack frame is pushed on the stack which reserves just enough space for all the local variables in the scope of foo to fit. If another function bar were to be called from within foo, its stack frame would be pushed on top of foo's. For this to work (efficiently), the size of the stack frame (by extension all local variables in foo, including the array arr) must be known to the compiler.

When the functions return (first bar, then foo) their stack frames are popped in reverse order of their creation, and thus the stack memory remains defragmented at all times and the location of each and every local variable is determined at compile time, hence the relative efficiency. Heap memory can have a dynamic size but this comes at the cost of having to allocate a suitably sized spot on the heap.

You can also see this dichotomy in the standard library containers std::vector and std::array. std::array is effectively just a wrapper around C-style arrays and thus its size needs to be known at compile time and is therefore specified as a template parameter, e.g. std::array<char, 42> wraps char[42]. Unlike in your case, the compiler will (rightly) complain if you use a runtime variable as the second template parameter. You can however safely use any constant expression (e.g. result of a constexpr function).

Jonas Greitemann
  • 1,011
  • 10
  • 25