Разработчик
Проверенный
Участник
Пользователь
- Сообщения
- 207
- Реакции
- 420
- Помог
- 10 раз(а)
Введение в программирование на SourcePawn. Типы переменных, структура кода.
SourcePawn знает 6 основных типов переменных (в списке их, на самом деле, 7, но последний - "волшебный"):
- int - целочисленное число, занимает в памяти 4 байта. Допустимое число для хранения в этой переменной - от -2147483648 до 2147483647. Эти числа, кстати, можно получить в коде. Они представлены константами cellmin и cellmax, соответственно.
- char - символ строки, занимает в памяти 1 байт. SourcePawn полностью поддерживает Unicode.
- float - числа с плавающей запятой (дробные), занимают в памяти 8 байт.
- Handle - указатель на некоторые переменные в памяти самого SourceMod, занимает 4 байта. Этим типом может быть представлено что угодно, начиная с соединения к БД, заканчивая самим плагином. Мы к этому типу ещё вернёмся в отдельной статье.
- Address - адрес в памяти самого сервера, занимает 4 байта.
- Function - указатель на функцию, занимает 4 байта.
- any - волшебный тип. Точный размер, занимаемый этим типом переменной, варьируется от 4 до 8 байт (в зависимости от того, что в неё в итоге записать).
В отличие от Си и любого нормального языка, где мы имеем функцию, которая является "входной точкой", SourcePawn её не имеет. Виртуальная машина вызывает его публичные функции, когда что-то происходит. Например, при старте плагина, вызывается OnPluginStart(), а при выгрузке - OnPluginEnd(). Мы ещё вернёмся к этому.
Теперь немного о структуре языка. Он "блочный".
Код:
void SomeFunction()
{
// Блок 1
DoSomeAction();
if (DoSomeResult() == true)
{
// Блок 2
PrintToServer("Yeah! DoSomeResult() returned true!");
{
// Блок 3
// SourcePawn может делать вложения блоков без каких-либо условий и циклов. Этим можно пользоваться, к слову. Все переменные, созданные в блоке, при выходе из него уничтожаются.
int iMyData = 1337;
PrintToServer("MyData equals to %d", iMyData);
// Конец блока 3
}
// Конец блока 2
}
// Конец блока 1
}
- Объявлена функция SomeFunction, которая ничего на вход не принимает, является скрытой (вызвать извне (из другого плагина или расширения), не передав указатель - нельзя), и ничего не возвращает (void). При входе в неё начинается выполнение блока "Блок 1"
- Вызывается функция DoSomeAction(), на которую ничего не передаётся (содержимое скобок - пусто), и ничего из неё не принимается (нет никакого приравнивания к некой переменной).
- В блоке условия (if) вызывается функция DoSomeResult(), на которую, снова, ничего не принимается, но результат которой записывается во временную переменную (которую не видно), и которая в конечном счёте сравнивается с true.
- Если значение совпало - виртуальная машина начинает выполнять содержимое блока "Блок 2". Если нет - пропускает его.
- В блоке 2 вызывается PrintToServer() функция, на которую передаётся некий текст.
- Далее виртуальная машина переходит к выполнению блока 3, т.к. никаких "условий" перед ним и циклов нет.
- В блоке 3 создаётся переменная типа int с именем iMyData. Ей сразу присваивается значение 1337.
- Вызывается PrintToServer() функция, на которую передаётся уже два аргумента: текст и переменная. Переменная копируется, потому любые изменения оной "на той стороне" не повлияют на неё в этом блоке.
Мы можем объявлять блоки где угодно. Но всё же, компилятор нас обязывает объявлять "блок" обязательно при объявлении функции (в старом синтаксисе, к слову, мы этого могли и не делать). Мы ещё вернёмся к этому при изучении "условий", "циклов", т.к. блоки в основном фигурируют именно там.
Для создания переменной, обычно делается запись вида:
Код:
тип_переменной название_переменной;
Код:
тип_переменной название_переменной = значение;
Код:
int g_iPi = view_as<int>(3.14);
Ну, и отмечу, что за попытку преобразовать переменные некоторого типа, компилятор вообще ругает. За попытку преобразовать char или Function во что-то иное, Вы гарантированно получите "ошибку".
Глобальные, локальные переменные. Константы.
Теперь возможно имеет смысл поднять тему, что же это такое, переменные.
Если проводить аналогию, то каждый из Вас рано или поздно сталкивался в школе на математике с подобием переменных - x (икс), y (игрек), и так далее. Обычно в уравнениях надо найти
x
, зная какие-то другие переменные. Как и в математике, переменная в себе что-то хранит: число, указатель на участок памяти, символ.Вот только в отличие от математики, в программировании выделяют два типа переменных: глобальные и локальные.
Глобальные доступны во всём коде. Мы можем редактировать их значения из одной функции, читать из второй, передавать какому-то другому плагину из третьей, и так далее... Они нам доступны всегда без каких-либо лишних телодвижений. Память для них выделяется виртуальной машиной при старте плагина. Объявляются они вне функций.
Локальные же наоборот. Память для них выделяется на время выполнения функции, и после выполнения, очищается. А объявлены прямо в теле функции.
Чтобы проще было понять, приведу фрагмент кода:
Код:
int g_iData; // глобальная переменная
public void OnPluginStart() {
g_iData++;
DoLogic();
g_iData++;
DoLogic();
// вызовет ошибку ещё на стадии компиляции:
// PrintToServer("%d", iData);
}
void DoLogic() {
int iData; // локальная переменная
iData++;
PrintToServer("%d %d", g_iData, iData);
}
Код:
1 1
2 1
iData
снова и снова выделяется. По-умолчанию, значение переменной - это 0. После выполняется увеличение на единицу, и вывод глобальной переменной, и локальной в консоль сервера.
Последнее редактирование: