Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.

Реклама


 

**Как получить V.I.P** (Перейти)
Чтобы заказать рекламу на Pro-Pawn.Ru, обращайтесь в Skype.
Баннерная реклама 100руб/мес, Текстовая 50руб/мес.
Показано с 1 по 1 из 1
  1. #1
    Аватар для Daniel_Cortez
    new fuck_logic[0] = EOS;

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    1,489
    Репутация:
    2035 ±

    Мифы о Pawn-скриптинге - #4

    Внимание: данная тема закрыта для защиты от копирования.
    Если есть какие-то вопросы, замечания или просто пожелания по поводу данного урока - оставляйте их здесь.


    Миф 4: "В командах на ZCMD/DC_CMD лучше использовать params/params[0]/params[1], чем создавать новую переменную/массив."

    Статус: Опровергнут, Подтверждён.

    Описание:
    Похоже на предыдущий миф (рекомендуется к прочтению для понимания теории в данном мифе), но больше относится к командам.
    Пример кода:
    PHP код:
    CMD:example(playeridparams[])
    {
        
    sscanf(params"ud"params[0], params[1]);
        
    // ...

    Заблудшие обычно аргументируют использование ячеек массива params экономией памяти. На деле же этот единственный плюс незначителен и не оправдывает себя перед меньшей читаемостью и надёжностью кода.

    Доказательство:
      Открыть/закрыть
    В предыдущей статье было сказано, почему не стоит использовать массивы вместо одиночных переменных.
    В данной же статье будут рассмотрены дополнительные причины, почему не следует заменять все переменные на params[X] в командах.
    • Нет гарантии существования params[1], params[2], ...
      При использовании DC_CMD, если строка params пустая, в ней будет существовать только 0-я ячейка, в которой будет символ '\0', означающий конец строки (в случае с ZCMD будет комбинация из двух ячеек {'\1', '\0'}, но это всего лишь костыль, сделанный чтобы избежать краша из-за передачи пустой строки через CallLocalFunction).
      И если попытаться использовать ячейки с индексом больше 0 (params[1], params[2], etc.), возникнет ошибка доступа к неправильному участку памяти.
      Проверим это утверждение на практике:
      PHP код:
      #include <a_samp>
      #include <dc_cmd>

      CMD:test(playeridparams[])
      {
          
      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: хранение массивов. Чаще всего этими массивами оказываются строки.
    Рассмотрим следующий пример:
    PHP код:
    CMD:pm(playeridparams[])
    {
        new 
    targetid;
        
    sscanf(params"us[128]"targetidparams);
        if (
    == IsPlayerConnected(targetid))
            return 
    SendClientMessage(playerid, -1"Игрок не подключен!");
        return 
    SendClientMessage(targetid, -1params);

    В таком случае лучше будет сохранить текст сообщения в массив params.
    Во-первых, нет риска выйти за пределы массива. Если в нём помещается весь текст параметров команды, то часть текста и подавно влезет.
    Во-вторых, не нужно выделять место в стеке. Также не будет никаких потерь во времени из-за инициализации всех элементов массива нулями (эти потери ничтожно малы, но они всё же есть).
    В-третьих, особых проблем с понятностью кода возникнуть не должно. Если использовать params только для хранения текста, то при использовании params где-то ещё кроме sscanf (пример в коде выше: SendClientMessage(playerid, -1, params)), то станет понятно, что это какой-то текст - в данном случае это текст для личного (PM) сообщения.
    Таким образом, в случае с сохранением текста из команды массив params может пригодиться, т.к. у такого подхода практически нет никаких минусов.

    Итог:
    • Для использования отдельных ячеек массива params вместо локальных переменных - миф опровергнут.
    • Для использования массива params целиком для сохранения текста из параметров команды - миф подтверждён.



    Вывод: Использование ячеек params вместо одиночных переменных чревато запутыванием кода (запоминать, что находится в params[0], а что в params[1] и params[2] мазохизму подобно).
    Кроме того, размер params может меняться в зависимости от параметров команды, гарантировано только существование params[0]. Если попытаться сохранить что-то в другой ячейке, можно словить ошибку из-за доступа к невалидному участку памяти.
    Тем не менее, есть смысл использовать массив params для сохранения в него строк из самого себя.
    Пример: команда /pm [ID игрока/часть ника] [текст]
    PHP код:
    CMD:pm(playeridparams[])
    {
        new 
    targetid;
        
    sscanf(params"us[128]"targetidparams);
        if (
    == IsPlayerConnected(targetid))
            return 
    SendClientMessage(playerid, -1"Игрок не подключен!");
        return 
    SendClientMessage(targetid, -1params);



    Специально для Pro-Pawn.ru
    Копирование данной статьи на других ресурсах без разрешения автора запрещено!
    Индивидуально в PM и Skype по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).
    SA-MP 0.4 is a lie

  2. 15 пользователя(ей) сказали cпасибо:
    $continue$ (13.12.2015)Anton Styazhkin (12.12.2015)ArtZet (13.12.2015)BadPawn (20.02.2016)Engineer (15.05.2016)Geebrox (25.06.2016)LLIapuk (14.12.2015)Londlem (12.12.2015)Nurick (14.12.2015)Profyan (13.12.2015)Quman (13.12.2015)Reim (19.12.2015)Sp1ke (13.12.2015)while (27.06.2016)^_^ (13.12.2015)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •