开发者

When are variable-length arrays legal?

I'm not a C++ expert, but a开发者_StackOverflow中文版s far as I know this code should fail due to size not being constant:

#include<iostream>

using namespace std;

int main(int argc, char** argv)
{
  int size = *argv[1] - 48;
  char array [size];
  cout<<sizeof(array)<<endl;

  return 0;
}

Why does this work when I compile that with gcc (better say g++)?

./test 7
7
/test 2 
2


To allocate memory from stack or heap for a variable, the size of the variable need to be known. C++ compilers can decide themselves how they allocate memory, but c++ has made it public how they expect c++ compilers to handle the situation, and thus c++ std requires that compiler vendors publish their memory handling. This happens via sizeof operator. This operator is calculated completely in compile-time. The compile-time restriction for the array sizes comes from this requirement.

int arr[10];
std::cout << sizeof(arr) << std::endl

since every variable and type supports sizeof, their sizes need to be calculated on compile-time in c++. Thus variable-length arrays are impossible in c++.

There is another very important restriction flowing from this requirement. In principle c++ compiler vendors could calculate maximum amount of memory required for c++ program's stack, if only there weren't one problem: for recursive functions, you cannot calculate stack size used by the program, but for everything else, the size of stack can be calculated by doing the following:

  1. use sizeof(a) for every variable in stack frame
  2. sum the sizes of the variables to get amount of memory required for that stack frame
  3. list all possible stack frames and calculate their sizes
  4. Pick the call stack that has largest size
  5. choose that size as the size of your program's stack.

Unfortunately, recursive functions break the whole scheme. And it would need global program's flow analysis to regognize which functions have possibly infinite call stacks. But the limitation for compile-time sizeof operator is important or our c++ programs would randomly run out of stack space, causing crashes and unstability. And this is unacceptable. Thus every variable and type supports compile-time sizeof operator.

VLA support requires that compilers can generate code where offsets normally generated to as constants to the resulting machine code are actually modifiable on runtime. Standard conforming c++ compilers normally do not have ability to do this. C decided to add this support and thus C compilers can do it. But in the process they needed to break the sizeof operator. No longer can the sizes be calculated on compile-time. VLA support as specified in the C standard has big problems:

  1. you cannot put VLA inside a struct or class
  2. VLA's are basically restricted to the local function scope

These problems were already solved in c++ via std::vector which do not have any of these problems.


Here is a list of new features in C99 which adds variable length arrays.

Also see $6.7.6.2/4 Array declarators of N1548(ISO/IEC 9899:201x Committee Draft — December 2, 2010 N1548) which details it.


That's a non-standard GCC extension - other compilers like Visual C++ don't support that.


It's a C99 feature that allows you to declare arrays like that on the stack.


c99 supports variable length arrays(VLA) but neither c90 nor C++ supports variable length arrays, but gcc support this as an extension in both C and C++ you can see this more clearly if you compile with these arguments:

gcc -std=c89 -pedantic

this will give you the following warning:

warning: ISO C90 forbids variable length array ‘array’ [-Wvla]

or with g++:

g++ -pedantic

will give you this warning:

warning: ISO C++ forbids variable length array ‘array’ [-Wvla]

this standards section in the gcc manual goes into more details. Important to note that as of the 2011 C standard variable length arrays(VLA) are now optional.


Even without VLA extensions, the code can compile when the compiler has failed to deduce that the dimension expression is not known at compile-time. It's still UB.


Because you don't invoke g++ as a C++ compiler. If I try it, I get a warning, stating clearly that "ISO C++ forbids variable length array". But my makefiles include the option -std=c++98, at least when I want to compile portable C++.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜