PDA

Просмотр полной версии : [Вопрос] Чем грозит возврат массива?



Igoreshka
28.03.2019, 23:25
format(str,sizeof(str),"%s %s удалил админ данные ''%s''",AdminRang(playerid),sendername(playerid),inputtext);
stock AdminRang(playerid)
{
new text[24];
switch(Player[playerid][pAdmin])
{
case 1: text = "Помощник";
case 2: text = "Ст.Помощник";
case 3: text = "Мл.Администратор";
case 4: text = "Администратор";
case 5: text = "Ст.Администратор";
case 6: text = "Администратор Фракций";
case 7: text = "Администратор Банов";
case 8: text = "Администратор Ивентов";
case 9: text = "Зам.Гл.Админинистратора";
case 10: text = "Гл.Администратор";
case 11: text = "Разработчик";
}
return text;
}
Что будет происходит с памятью, объяснить.

DeimoS
29.03.2019, 05:18
Ну функция возвращает текст, так? Этот текст нужно где-то хранить. Соответственно, каждый вызов функции память будет резервироваться в стеке.

Если это просто последовательный вызов функции, а-ля:

printf("1) %s", AdminRang(playerid));
printf("2) %s", AdminRang(playerid));
printf("3) %s", AdminRang(playerid));
То каждый вызов функции будет как-бы создавать локальный массив на 24 ячейки (так как ты возвращаешь массив в 24 ячейки), записывать в него данные, передавать их в printf и отчищать память. То бишь, постоянно будут лишние действия по инициализации/очищению памяти, что не так страшно, но всё же не желательно.

Страшнее будут последствия, если вызов функций будет внутри какой-то другой функции, а не последовательно:

printf("1) %s %s", AdminRang(playerid), AdminRang(playerid));
Тут уже функции будут потреблять не 24 ячейки, а 48, так как нам нужно хранить результат обоих вызовов функции, а не только одного. Если вызовов будет 3 - будет выделено уже 72 ячейки. Ну и так далее.
В общем, таким образом легко заполнить весь стек и получить его переполнение. Именно поэтому и не советуют заниматься возвратом строк. Достаточно сделать так:


stock GetAdminRankName(playerid, rank_name[])
{
switch(Player[playerid][pAdmin])
{
case 1: rank_name = "Помощник";
case 2: rank_name = "Ст.Помощник";
case 3: rank_name = "Мл.Администратор";
case 4: rank_name = "Администратор";
case 5: rank_name = "Ст.Администратор";
case 6: rank_name = "Администратор Фракций";
case 7: rank_name = "Администратор Банов";
case 8: rank_name = "Администратор Ивентов";
case 9: rank_name = "Зам.Гл.Админинистратора";
case 10: rank_name = "Гл.Администратор";
case 11: rank_name = "Разработчик";
}
return 1;
}
И использовать функцию так:

new rank_name[24];
GetAdminRankName(playerid, rank_name);
printf("1) %s %s %s", rank_name, rank_name, rank_name);
И всё, этот код в любом случае будет потреблять 24 ячейки.

P.S. Хотя в твоём случае лучше вынести имена рангов в глобальный массив:

new const AdminRankName[][24] =
{
"Помощник",
"Ст.Помощник",
"Мл.Администратор",
"Администратор",
"Ст.Администратор",
"Администратор Фракций",
"Администратор Банов",
"Администратор Ивентов",
"Зам.Гл.Админинистратора",
"Гл.Администратор",
"Разработчик"
};
А потом обращаться к нему напрямую, отнимая единицу от текущего уровня админа (так как ячейки в массиве с 0 начинаются, а уровень с 1)

format(str,sizeof(str),"%s %s удалил админ данные ''%s''", AdminRankName[Player[playerid][pAdmin]-1], sendername(playerid), inputtext);
Только нужно всегда следить, чтоб уровень админки был больше 0 и меньше 12 (1-11), дабы при обращении к массиву не получить выход за его пределы.
Можно написать макрос для удобства:

#define GetAdminRankName(%0) AdminRankName[Player[%0][pAdmin]-1]
//
format(str,sizeof(str),"%s %s удалил админ данные ''%s''", GetAdminRankName(playerid), sendername(playerid), inputtext);

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

Igoreshka
29.03.2019, 14:38
Спасибо. Теперь понял.