Вход

Просмотр полной версии : [Вопрос] Пару вопросиков



InCorrect
30.12.2015, 11:56
Доброго дня, решился все таки и я задать парочку вопросов по программированию Pawn

1. В чем разница между этим

CMD:ahelp(playerid)
{
new level = PlayerInfo[playerid][pAdmin];
if(level >= 1) SendClientMessage(playerid, GREEN, "Доступные команды:"), SendClientMessage(playerid, YELLOW, "1 уровень: ...");
if(level >= 2) SendClientMessage(playerid, YELLOW, "2 уровень: ...");
// и так далее
return true;
}

и этим
CMD:ahelp(playerid)
{
if(PlayerInfo[playerid][pAdmin] >= 1) SendClientMessage(playerid, GREEN, "Доступные команды:"), SendClientMessage(playerid, YELLOW, "1 уровень: ...");
if(PlayerInfo[playerid][pAdmin] >= 2) SendClientMessage(playerid, YELLOW, "2 уровень: ...");
// и так далее
return true;
}

(В первом случае вводиться отдельная переменная)

Влияет ли это как-то на время выполнения кода?

2. Как можно эффективно экономить размер стэка?

Вот например если в абсолютно чистый мод вставить этот отрезок кода

static const welcome_message[] = "%s, добро пожаловать на сервер!";
new string[sizeof(welcome_message) - 2 + MAX_PLAYER_NAME + 1], player_name[MAX_PLAYER_NAME];
GetPlayerName(playerid, player_name, sizeof(player_name));
format(string, sizeof(string), welcome_message, player_name);
SendClientMessage(playerid, -1, string);
http://cs630019.vk.me/v630019613/8d9f/pjYVuwjr2GE.jpg
http://cs630019.vk.me/v630019613/8da6/wAacVEJnj0o.jpg

То размер стэка увеличиться аж на 81 ячейку.Получается еще буквально 50 таких переменных и будет достигнут (!) придел.А в мод еще нужно вместить около сотни (а то и двух) команд, примерно столько же диалогов, и еще прочую тучу различных систем.И как тут быть?

VVWVV
30.12.2015, 12:07
1. Нет разницы, если только немного.
2. Не удивительно, ведь в стек помещается информация: локальные переменные, название функции, возвращаемое значение и т.п. И следует знать, что после выполнения, функция автоматически выгружает заполненную память тем самым восстанавливая стек.

InCorrect
30.12.2015, 12:10
2. Не удивительно, ведь в стек помещается информация: локальные переменные, название функции, возвращаемое значение и т.п. И следует знать, что после выполнения, функция автоматически выгружает заполненную память тем самым восстанавливая стек.

То бишь не стоит бояться ограничения в 16384 байт?

Daniel_Cortez
30.12.2015, 12:25
1. В чем разница между этим

CMD:ahelp(playerid)
{
new level = PlayerInfo[playerid][pAdmin];
if(level >= 1) SendClientMessage(playerid, GREEN, "Доступные команды:"), SendClientMessage(playerid, YELLOW, "1 уровень: ...");
if(level >= 2) SendClientMessage(playerid, YELLOW, "2 уровень: ...");
// и так далее
return true;
}

и этим
CMD:ahelp(playerid)
{
if(PlayerInfo[playerid][pAdmin] >= 1) SendClientMessage(playerid, GREEN, "Доступные команды:"), SendClientMessage(playerid, YELLOW, "1 уровень: ...");
if(PlayerInfo[playerid][pAdmin] >= 2) SendClientMessage(playerid, YELLOW, "2 уровень: ...");
// и так далее
return true;
}

(В первом случае вводиться отдельная переменная)

Влияет ли это как-то на время выполнения кода?
Доступ к одиночным переменным быстрее, чем к ячейкам массива. Если же больше 1 раза производится доступ к ячейке многомерного массива, то лучше заранее кэшировать содержимое этой ячейки в локальной переменной.



2. Как можно эффективно экономить размер стэка?

Вот например если в абсолютно чистый мод вставить этот отрезок кода

static const welcome_message[] = "%s, добро пожаловать на сервер!";
new string[sizeof(welcome_message) - 2 + MAX_PLAYER_NAME + 1], player_name[MAX_PLAYER_NAME];
GetPlayerName(playerid, player_name, sizeof(player_name));
format(string, sizeof(string), welcome_message, player_name);
SendClientMessage(playerid, -1, string);
http://cs630019.vk.me/v630019613/8d9f/pjYVuwjr2GE.jpg
http://cs630019.vk.me/v630019613/8da6/wAacVEJnj0o.jpg

Может всё-таки объясните, что именно было "до", а что "после"? Вы пока что показали только один отрывок кода.



То размер стэка увеличиться аж на 81 ячейку.Получается еще буквально 50 таких переменных и будет достигнут (!) придел.А в мод еще нужно вместить около сотни (а то и двух) команд, примерно столько же диалогов, и еще прочую тучу различных систем.И как тут быть?

Ну вы же не собираетесь делать так, чтобы функция вызывала саму себя или другую функцию 50 раз?


Function1()
{
new array[100];
return Function2();
}

Function2()
{
new array[100];
return Function3();
}

// ...

Function50()
{
new array[100];
return random(0);
}


В программировании есть такое понятие, как блок: пространство, в пределах которого существуют локальные переменные.


SomeFunction()
{
new array[80];
// ...
}

В примере выше массив array будет существовать только пока выполняется функция. Как только функция завершит своё выполнение, она высвободит место в стеке, занятое под массив array.

Ещё пример:


SomeFunction()
{
if(IsPlayerConnected(0))
{
new array[80];
// #1
// ...
}
else
{
// #2
// ...
}
// #3
}

Здесь array существует только внутри блока ветвления if (точка #1). Фукнция зарезервирует место в стеке, как только начнётся выполнение положительной ветки if, и высвободит его по окончании выполнения ветки, поэтому в местах #2 и #3 место в стеке под массив расходоваться не будет.

InCorrect
30.12.2015, 12:38
Может всё-таки объясните, что именно было "до", а что "после"? Вы пока что показали только один отрывок кода.

До был чистый мод взятый прямиком с sa-mp.com.

Еще один вопрос, как в этом коде, правильно подсчитать размер переменной bigstring?

if(strcmp(cmd, "/leaders", true) == 0)
{
new bigstring[2048], totalLeaders = 0;
strcat(bigstring, "Организация - Должность - Имя - Телефон\n\n{FFFFFF}");
for(new i = 0; i < MAX_PLAYERS; i++)
{
new fractionname[96];
if(Logged[i] == true)
{
if(PlayerInfo[i][pAdmin] == 0 && PlayerInfo[i][pLeader] > 0)
{
totalLeaders++;
switch(PlayerInfo[i][pLeader])
{
case 1: fractionname = "Grove Street - Daddy";
case 2: fractionname = "The Ballas - Big Daddy";
case 3: fractionname = "Varios Los Aztecas - Padre";
case 4: fractionname = "Los Santos Vagos - Padre";
case 5: fractionname = "The Rifa - Padre";
case 6:
{
switch(PlayerInfo[i][pUnit])
{
case 0: fractionname = "Мин. внутренних дел - Министр внутренних дел";
case 1: fractionname = "Управление полиции ЛС - Генерал";
case 2: fractionname = "Управление полиции СФ - Генерал";
case 3: fractionname = "Управление полиции ЛВ - Генерал";
case 4: fractionname = "ФБР - Директор ФБР";
}
}
case 7:
{
switch(PlayerInfo[i][pUnit])
{
case 0: fractionname = "ТВ-Радио - Управляющий СМИ";
case 1: fractionname = "Радиоцентр ЛС - Директор радиоцентра";
case 2: fractionname = "Радиоцентр СФ - Директор радиоцентра";
case 3: fractionname = "Радиоцентр ЛВ - Директор радиоцентра";
case 4: fractionname = "Телецентр - Директор ТВ-Центра";
}
}
case 8:
{
switch(PlayerInfo[i][pUnit])
{
case 0: fractionname = "Мин. Обороны - Министр обороны";
case 1: fractionname = "Сухопутные войска - Генерал";
case 2: fractionname = "Военно-Воздушные силы - Генерал";
case 3: fractionname = "Военно-Морской флот - Адмирал";
}
}
case 9:
{
switch(PlayerInfo[i][pUnit])
{
case 1: fractionname = "Администрация президента - Президент";
case 2: fractionname = "Мэрия Лос-Сантос - Мэр города";
case 3: fractionname = "Мэрия Сан-Фиерро - Мэр города";
case 4: fractionname = "Мэрия Лас-Вентурас - Мэр города";
}
}
case 10: fractionname = "La Cosa Nostra - Don";
case 11: fractionname = "Yakuza - Кумитэ";
case 12: fractionname = "Русская Мафия - Вор в законе";
case 13:
{
switch(PlayerInfo[i][pUnit])
{
case 0: fractionname = "Мин. Здравоохранения - Министр здравоохранения";
case 1: fractionname = "Городская больница ЛС - Главный врач";
case 2: fractionname = "Городская больница СФ - Главный врач";
case 3: fractionname = "Городская больница ЛВ - Главный врач";
}
}
}
format(bigstring, sizeof(bigstring), "%s%s - %s - %d\n", bigstring, fractionname, PlayerInfo[i][pName], PlayerInfo[i][pPhone]);
}
}
}
if(totalLeaders > 0)
{
ShowPlayerDialog(playerid, 337, DIALOG_STYLE_MSGBOX, "{FFCC00}Лидеры организаций в сети:", bigstring, "Закрыть","");
}
else
{
return SendClientMessage(playerid, COLOR_GRAD2, "В данный момент лидеров нет в сети.");
}
return 1;
}

VVWVV
30.12.2015, 12:50
Придётся менять всю структуру кода.

Profyan
30.12.2015, 12:56
Доступ к одиночным переменным быстрее, чем к ячейкам массива. Если же больше 1 раза производится доступ к ячейке многомерного массива, то лучше заранее кэшировать содержимое этой ячейки в локальной переменной.



Может всё-таки объясните, что именно было "до", а что "после"? Вы пока что показали только один отрывок кода.


Ну вы же не собираетесь делать так, чтобы функция вызывала саму себя или другую функцию 50 раз?


Function1()
{
new array[100];
return Function2();
}

Function2()
{
new array[100];
return Function3();
}

// ...

Function50()
{
new array[100];
return random(0);
}


В программировании есть такое понятие, как блок: пространство, в пределах которого существуют локальные переменные.


SomeFunction()
{
new array[80];
// ...
}

В примере выше массив array будет существовать только пока выполняется функция. Как только функция завершит своё выполнение, она высвободит место в стеке, занятое под массив array.

Ещё пример:


SomeFunction()
{
if(IsPlayerConnected(0))
{
new array[80];
// #1
// ...
}
else
{
// #2
// ...
}
// #3
}

Здесь array существует только внутри блока ветвления if (точка #1). Фукнция зарезервирует место в стеке, как только начнётся выполнение положительной ветки if, и высвободит его по окончании выполнения ветки, поэтому в местах #2 и #3 место в стеке под массив расходоваться не будет.

Как происходит подсчет стека?Просто была такая ситуация, что локальные массивы убирал вообще, но стек не менялся. Т.е компилятор высчитывает в каком блоке используется самое большое кол-во байт??
И еще: стек - это на весь мод, или стек - для каждого игрока.Если есть, например, функция и в ней массив(допустим) с 4000 ячейками.И если эта функция вызовется одновременно двумя игроками, то переполнение будет?(4000*4*2 = 32000 байт)

VVWVV
30.12.2015, 13:03
Как происходит подсчет стека?Просто была такая ситуация, что локальные массивы убирал вообще, но стек не менялся. Т.е компилятор высчитывает в каком блоке используется самое большое кол-во байт??
И еще: стек - это на весь мод, или стек - для каждого игрока.Если есть, например, функция и в ней массив(допустим) с 4000 ячейками.И если эта функция вызовется одновременно двумя игроками, то переполнение будет?(4000*4*2 = 32000 байт)
Стек для всех. Как минимум, переполнения из-за одной и той же функции не должно быть.

InCorrect
30.12.2015, 13:17
Еще такой вопросик, есть ли где-то с свободном доступе мод, который с легкостью выдержит онлайн в 1000 человек?

UPD
То бишь не стоит бояться ограничения в 16384 байт?

VVWVV
30.12.2015, 13:20
Еще такой вопросик, есть ли где-то с свободном доступе мод, который с легкостью выдержит онлайн в 1000 человек?
Как минимум, почти все моды могут выдержать онлайн 1000, но, однако, не все могут удержать этот онлайн, например, из-за лагов и т.п. Все зависит от машины, а также от производительности мода.

UPD:

То бишь не стоит бояться ограничения в 16384 байт?
Стоит. Мод можно написать так, что стек кончится.

InCorrect
30.12.2015, 13:24
Ну вроде бы вопросов больше нет
Тему можно прикрыть
Большое спасибо за ответы.С наступающим новый годом!