Bug? Несоответствие описания в справке и поведения локального массива при инициализации

 

Приветствую всех.

Поиск причины странного поведения собственного индикатора привел к излагаемому здесь результату.

В разделе "Инициализация переменных" справочной системы (223 билд) читаем:

..Любая переменная инициализируется нулем (0), если явно не задано другое начальное значение. ..Инициализация локальных переменных производится каждый раз при вызове соответствующих функций..

Создаем простой индикатор.

Вариант 1:

#define  MAX_LEVELS  14

#property indicator_chart_window
#property indicator_buffers 1

extern  int  paramNoUsed = 4;

double TestBuff[];

void init()
{
    IndicatorDigits(Digits);
    SetIndexBuffer(0, TestBuff);
    SetIndexStyle (0, DRAW_LINE);

    IndicatorShortName("Test");
    SetIndexLabel(0, "Test");
}
//=========================================================

void start()
{
    Test(99);
    Test(99);
    Test(99);
}
//=========================================================

void Test (int StartBar)
{
// счетчик вызовов функции
static int s_count;
    s_count++;
//  Нужно, чтобы при каждом вызове массив a[] имел нулевые элементы
/*!*/double a[MAX_LEVELS];
    ///////////////////////////////////////////////////////
    //  Some Calculation
    for (int k = StartBar; 0 <= k; k--) {
        for (int j = 0; j < MAX_LEVELS; j++) {
            a[j] += 1;
        }
    }
    Print("Test(",s_count,")=", a[0], " ", a[1], " ", a[2], " ", a[3], " ", a[4], " ", a[MAX_LEVELS-1]);
}
//=========================================================

Ясно, что индикатор ничего не рисует, результат смотрим в окне «Терминал» на закладке Эксперты. Видим:

Test(1)=100 100 100 100 100 100

Test(2)=200 200 200 200 200 200

Test(3)=300 300 300 300 300 300

Неожиданный результат - только один раз проходит инициализация элементов массива, далее локальный массив ведет себя как статический.

Вариант 2. Читаем об инициализации массивов:

..Список значений элементов массива должен быть заключен в фигурные скобки.

Пропущенные инициализирующие значения считаются равными 0..

ну как в "до боли знакомом" С и С++ :)

Исправляем строку кода, помеченную /*!*/ на:

double a[MAX_LEVELS]={0};

и имеем:

Test(1)=100 100 100 100 100 100

Test(2)=100 200 200 200 200 200

Test(3)=100 300 300 300 300 300

Каждый раз обнуляется только 0-ой элемент массива, в остальном – аналогично предыдущему случаю.

Вариант 3. Bypass несложен. Добавим после строки /*!*/ вызов:

ArrayInitialize(a, 0);

Теперь все в порядке:

Test(1)=100 100 100 100 100 100

Test(2)=100 100 100 100 100 100

Test(3)=100 100 100 100 100 100

Вывод. Да он уже сформулирован в заголовке.

Скорее всего, программеры с многолетним опытом уже натыкались на это, а для новичков мой пост будет предостережением от досадной ошибки. Ну а если разработчики компилятора исправят либо инициализацию локальных массивов, либо описание в справке, будет совсем хорошо.

 
Да, массивы могут приподнести сюрпризы в MQL4. Смотрите ветку https://www.mql5.com/ru/forum
 
Благодарю, Rosh, за ссылку.
Оказывается об этой проблеме заговорили более года назад, "а воз и ныне там..." Не понимаю разработчиков. Ведь можно же в справке честно написать, что локальные массивы требуют явной инициализации. И все. Не будет досадной траты времени на то, чтобы устанавливать это экспериментальным путем.
 

Частично указано в справке по функции ArrayResize():

Устанавливает новый размер в первом измерении массива. При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера, в противном случае возвращает -1, и массив не меняет размеры.


Замечание: массив, объявленный на локальном уровне в какой-либо функции, у которого был изменен размер, останется неизменным после завершения работы функции. При повторном вызове функции такой массив будет иметь размер, отличный от объявленного.