WarCraft 3: 19. Расширенная индексация

vJass

Содержание главы:

Введение

Мы очень много говорили о предельном размере Jass-массива, о том что этот предел сильно сказывается на работе JassHelper, ограничивая нас в количестве экземпляров структуры, типа-массива и т.д. Тем не менее, у нас есть возможность преодолеть данное ограничение. Это возможно путем объявления нескольких Jass-массивов, допустим, для одной структуры, чье максимальное количество экземпляров превышает максимальный размер Jass-массива. Однако, такой подход требует жертв:
  • Поскольку для данного трюка используется дополнительный вызов функции, мы получаем результат который работает ощутимо медленнее, чем если мы укладываемся в лимит, работая с обычным массивом
  • Выполнение такой функции само по себе требует выполнения операций в количестве новаяРазмерность/8192
  • Если вы используете огромные значения размерности, количество требуемых операций может оказаться чрезвычайно большим. Например, если ваша структура имеет 20 атрибутов и вы расширили предел количества экземпляров до 60 000, компилятор сгенерирует порядка 40 новых функций в 16 инструкций каждая.
Некоторые Jass-программы могут требовать индексацию свыше существующего предела, однако, может оказаться и так, что данное требование опционально и работа программы вполне может уложиться в существующий лимит. Другими словами, написанная система имеет определенную гибкость в размерности. По этой причине, синтаксис позволяет использовать константы для задания размерности. JassHelper, в свою очередь, будет генерировать расширенную индексацию только в случае преодоления предела в 8191 (или 8190 для структур, поскольку индекс 0 зарезервирован как нулевое значение).
Тем не менее, JassHelper обладает внутренним ограничением, что запрещает объявлять размерность, которая потребовала бы сгенерировать более дополнительных 8 массивов на расширение индексации для одного большого массива. Но даже в этом случае, индексация имеет ограничение в районе 408 000, что само по себе является безумным числом. Я не могу представить ситуацию, в которой потребовалось бы больше.

Глобальные массивы

Глобальные массивы порой могут востребовать расширенную индексацию, свыше существующего предела. Для этого размер массива указывается явно:
globals
    integer array myArray [9000]
endglobals
В таком случае, у массива появится атрибут size, который позволяет узнать заданную при объявлении размерность. Вы так же можете указать размер массива, не превышающий предела, в таком случае атрибут size тоже будет добавлен
globals
    integer array myArray [500]
endglobals

function test takes nothing returns nothing
 local integer i=0

    call BJDebugMsg(I2S(myArray.size)) //prints 500

    loop
        exitwhen i>=myArray.size
        set myArray[i]=i
        set i=i+1
    endloop
endfunction
Для указания размерности можно использовать константу
globals
    constant integer Q = 60000
    integer array myArray [Q]
endglobals
Тот же синтаксис доступен статичным атрибутам структур
struct MyStruct
    static integer A[10000]
endstruct

Двумерные массивы

Расширенная индексация доступна двумерным массивам. В этом случае, атрибут size будет содержать размер в виде произведения ширины и высоты массива
globals
    integer array mat1 [10][20]

    constant integer W = 100
    constant integer H = 200
    integer array mat2 [W][H]
endglobals

function test takes nothing returns nothing
    local integer i = 0
    local integer j = 0
    local integer c = 0
    call BJDebugMsg(I2S(mat1.size)) // Выведет 200 (10 * 20)

    // Заполнение массива:
    loop
        exitwhen (i==mat1.width)
        set j=0
        loop
            exitwhen (j==mat1.height)
            set c=c+1
            set mat1[i][j]=c
            set j=j+1
        endloop

        set i=i+1
    endloop

    call BJDebugMsg( I2S( mat1[0][1]  )  ) // Выведет 2

    call BJDebugMsg( I2S( mat2.width) ) // Выведет 100
endfunction

Тип-массив

Тип-массив уже использует в своем синтаксисе указание размера при объявление, а так же по умолчанию обладают атрибутом size. Тем не менее, если вы хотите указать расширенную индексацию, вы должны это сделать сразу после указания размерности, через запятую:
type MyArray extends integer array [200] // Обычный тип-массив, максимум 40 экземпляров

type MyArray extends integer array [200, 40000] // Тип-массив с расширенной индексацией, максимум 200 экземпляров

Структуры

У нас есть структура
struct Point
    real x
    real y
endstruct
По какой-то причине нам недостаточно 8190 экземпляров, поэтому мы расширяем индексацию до 10 000 экземпляров
struct Point[10000]
    real x
    real y
endstruct
Не забываем о дополнительном ограничении, которое накладывается при использовании массива в атрибутах структуры
struct Points[10000]
    real array x[2]
    real array y[5]
endstruct
Данная структура имеет ограничение в 2000 экземпляров.
Вы не можете указывать расширенную индексацию для структур, которые расширяют другую структуру или интерфейс
struct X[10000] extends Y // Ошибка!
    integer a
    integer b
endstruct

interface A[20000] // Допустимо
    method a takes nothing returns nothing
endinterface

struct B extends A
    method a takes nothing returns nothing
        call BJDebugMsg("...")
    endmethod
endstruct

struct C[20000] // Допустимо
    integer x
endstruct

struct D extends C
    integer y
endstruct
Обратите внимание, что расширяющая структура наследует расширенную индексацию от родителя. Структуры A, B, C и D имеют ограничение в 20 000 экземпляров.
Ситуация немного иная с массивом структуры, для которой вы не можете указывать расширенную индексацию. Однако, вы можете объявить массив структуры размерностью превыше лимита
struct A[20000] extends array[30000] // Ошибка!
    /* 
        ...
    */
endstruct

struct B extends array[10000] // Допустимо
    /* 
        ...
    */
endstruct

Просмотров: 292

Комментарии пока отсутcтвуют