В предыдущей статье было сказано, почему не стоит использовать массивы вместо одиночных переменных.
В данной же статье будут рассмотрены дополнительные причины, почему не следует заменять все переменные на params[X] в командах.
- Нет гарантии существования params[1], params[2], ...
При использовании DC_CMD, если строка params пустая, в ней будет существовать только 0-я ячейка, в которой будет символ '\0', означающий конец строки (в случае с ZCMD будет комбинация из двух ячеек {'\1', '\0'}, но это всего лишь костыль, сделанный чтобы избежать краша из-за передачи пустой строки через CallLocalFunction).
И если попытаться использовать ячейки с индексом больше 0 (params[1], params[2], etc.), возникнет ошибка доступа к неправильному участку памяти.
Проверим это утверждение на практике:
#include <a_samp>
#include <dc_cmd>
CMD:test(playerid, params[])
{
params[1] = 0; // Если строка params пустая, 1-й ячейки не будет существовать.
}
main()
{
cmd::test(0, ""); // Вызываем команду с пустой строкой.
}
При запуске с плагином crashdetect в консоль будет выведено сообщение об ошибке: "Invalid memory access".
Без crashdetect под Windows никакого эффекта не будет, но под Linux возникнет краш.
Отсюда и львиная доля крашей серверов на хостинге, которые не возникают на локальном сервере.
- Запутывание кода.
Для отдельных переменных можно использовать свои имена, по которым эти переменные можно отличить друг от друга и легко понять их назначение.
Если же использовать вместо переменных ячейки массива, этим ячейкам нельзя задать отдельные названия - они различаются только по индексам, которые сложнее удерживать в голове, если в команде используется несколько ячеек params. Это может привести к путанице как у людей, которые просто читают такой код, так и у самого автора кода, который может случайно использовать не ту ячейку.
Справедливости ради, следует заметить, что при использовании 0-й ячейки массива params компилятор оптимизирует обращения к этой ячейке до 1 инструкции вместо 2 (см. предыдущую статью об использовании массивов).
Благодаря этому обращение к params[0] происходит с такой же скоростью, как и к одиночной переменной, но при этом никаких дополнительных объёмов памяти, как с одиночной переменной, выделять не нужно.
Тем не менее, это правило действует только для нулевых ячеек. Для ячеек с индексами 1, 2, 3, ... выгоднее всё же использовать локальные переменные.
К тому же в современных реалиях лучше обеспечить читаемость и надёжность кода, чем рисковать ради экономии каких-то 4 байт оперативы.
Сервера запускаются не на калькуляторах, а на хостингах, которые предоставляют десятки и даже сотни мегабайт оперативной памяти.
Получается, что если использовать ячейки params, как замену одиночным переменным, то единственный плюс такого подхода незначителен, а значит утверждение о выгоде использования ячеек массива params в этом плане можно считать ложным.
Но остаётся ещё одно применение для params: хранение массивов. Чаще всего этими массивами оказываются строки.
Рассмотрим следующий пример:
CMD:pm(playerid, params[])
{
new targetid;
sscanf(params
, "us[128]", targetid
, params
); }
В таком случае лучше будет сохранить текст сообщения в массив params.
Во-первых, нет риска выйти за пределы массива. Если в нём помещается весь текст параметров команды, то часть текста и подавно влезет.
Во-вторых, не нужно выделять место в стеке. Также не будет никаких потерь во времени из-за инициализации всех элементов массива нулями (эти потери ничтожно малы, но они всё же есть).
В-третьих, особых проблем с понятностью кода возникнуть не должно. Если использовать params только для хранения текста, то при использовании params где-то ещё кроме sscanf (пример в коде выше: SendClientMessage(playerid, -1,
params)), то станет понятно, что это какой-то текст - в данном случае это текст для личного (PM) сообщения.
Таким образом, в случае с сохранением текста из команды массив params может пригодиться, т.к. у такого подхода практически нет никаких минусов.
Итог:
- Для использования отдельных ячеек массива params вместо локальных переменных - миф опровергнут.
- Для использования массива params целиком для сохранения текста из параметров команды - миф подтверждён.