Просмотр полной версии : [Вопрос] Доступ к двухмерному массиву
Как правильно получить в плагине доступ к двухмерному массиву?
Пример:
enum Info
{
Data1[10],
Data2,
};
native function(Array[][Info], size = sizeof array);
main()
{
new Array[][Info] = {
{ "228", 228 },
{ "100", 100 },
{ "1337", 1337 }
};
function(Array);
}
С проблемой разобрался, но всё равно не понятно, как оно работает.
(Код на павн в посте сверху учитывается)
cell AMX_NATIVE_CALL Function(AMX *amx, cell *params)
{
cell* addr;
amx_GetAddr(amx, params[1], &addr);
int i, len;
char string[10];
// params[2] == размеру массива, в данном случае 3
// 10 - это размер массива (первого элемента) в энуменаторе
// 1 - размер второго элемента
for (i = params[2]; i < params[2] * (10 + 1) + params[2];)
{
amx_StrLen(&addr[i], &len);
amx_GetString(string, &addr[i], NULL, len + 1);
i += 10;
something = addr[i]; // addr[i] - это второй элемент энуменатора
i++;
}
return 1;
}
Каждую итерацию цикла, в string записывается первый, а в something второй элемент
И, как раз таки, не понятно, почему i начинается со значения params[2]
Daniel_Cortez
02.07.2021, 09:53
Суть в том, что в многомерных массивах данные располагаются не совсем обычным образом.
В двухмерных массивах перед содержимым массива указываются смещения до содержимого каждой строки второго измерения.
Например, если у нас есть такой массив:
new a[2][3] = {
{ 0xA, 0xB, 0xC },
{ 0xD, 0xE, 0xF }
};
то в файл *.amx попадёт следующее:
8 10 ; смещения (8 и 16 в десятичной системе)
a b c ; строка 0
d e f ; строка 1
Т.е. если требуется получить значение элемента a[1][2], то следует:
Взять адрес массива.
Прибавить номер строки 2-го измерения, умноженный на размер ячейки (в примере выше нужен элемент из 1-й строки; размер ячейки равен четырём; 1 * 4 = 4).
Прочесть значение из получившегося адреса (в примере выше это будет 10), это значение и будет смещением данных 2-й строки. Прибавить прочитанное значение к уже имеющемуся адресу.
Прибавить номер ячейки в 2-м измерении, умноженный на размер ячейки (в примере - 2 * 4 = 8).
Снова прочесть значение по получившемуся адресу. Это и будет значение из a[1][2].
Сделана эта галиматья со смещениями потому, что в Pawn строки последнего измерения могут заполняться не до конца.
Например, если сделать так:
new a[2][] = {
{ 0xA, },
{ 0xD, 0xE, 0xF }
};
то в *.amx попадёт:
8 8 a d e f
На крупных массивах это может здорово сэкономить память. Собственно, Pawn и разрабатывался с расчётом на микроконтроллеры, у которых обычно очень ограниченный объём памяти.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot