Указатели и массивы в C++

Прошу объяснить, в чем разница в следующих листингах:

1)

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int a[n];
    for (int i=0; i<n; i++)="" cin="">> a[i];
    cout << endl;
    for (int i=0; i</n;></iostream>

2)

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int * a = new int[n];
    for (int i=0; i<n; i++)="" cin="">> a[i];
    cout << endl;
    for (int i=0; i</n;></iostream>

Насколько я знал, в первом варианте n должна быть const, и, собственно, код на листинге 1 не должен компилироваться, однако он работает (оттестировано на gcc-c++-4.4.0-mingw32)! Почему?

4 ответа

Ни один из стандартов C++, даже C++11, не включает в себя variable length arrays, просто некоторые компиляторы поддерживают их в качестве расширений. Такая же история с типом long long, правда его все-таки включили в C++11. Чтобы заставить g++ ругаться на такие нестандартные расширения нужно добавить опцию -pedantic:

$ cat test.cpp 
#include <iostream>

int main() {
    long long int a;
    std::cin >> a;
    int b[a];
}
$ g++ test.cpp  -pedantic
test.cpp: In function ‘int main()’:
test.cpp:4:5: warning: ISO C++ 1998 does not support ‘long long’ [-Wlong-long]
test.cpp:6:12: warning: ISO C++ forbids variable length array ‘b’ [-Wvla]
$ g++ test.cpp  --std=c++0x -pedantic
test.cpp: In function ‘int main()’:
test.cpp:6:12: warning: ISO C++ forbids variable length array ‘b’ [-Wvla]
</iostream>


В первом случае массив размещается в стеке, а во втором в куче (динамической памяти).

Основное отличие в том, что в стеке ограничен размер массива. Так например при n = 100000 программа работает, а при n = 1000000 уже нет (валится). Для кучи возможный размер значительно больше. 250000000 работает, а 500000000 - уже нет.

Собственно у меня Windows 7 (64-bit), но MinGW 32-разрядный gcc (GCC) 3.4.5 (mingw-vista special r3)


Под рукой черновик стандарта ISO/IEC JTC1 SC22 WG21 N3092, там указано:

8.3.4 Arrays [dcl.array]

In a declaration T D where D has the form

D1 [ constant-expression_opt ] attribute-specifier_opt

(...) If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

Откуда следует, что это поведение не соответствует стандарту. Возможно, в более поздних версиях стандарта это уже не так.

UPD: Проверил по последней версии черновика стандарта, аналогично.


А действительно - почему? Значит, в современных версиях компиляторов происходит динамическое создание массивов, объявленных как a[x]. Надо копаться в современных спецификациях. Хороший вопрос.

licensed under cc by-sa 3.0 with attribution.