Введение: Не смотря на то, что на дворе 2011 год, хочу предоставить новый способ, который по-моему мнению здесь ещё никто не представлял, способ хранения в битах. Начнем с того, что такое флаг, флаг по-другому говоря булевое значение, 1 или 0, true или false, на живом примере мы можем это представить в виде того, что игрок купил какую-нибудь вещь, и затем, чтобы проверить есть ли она у него, мы проверяем переменную, если 1, значит есть, иначе 0 - нет, то есть всего для хранения двух значений ноль и один. Многие не используют даже тип bool, создают направленно переменные с целыми числами, где одна ячейка равна 4 байтам, где, если быть точным можно было хранить целых 32 флага, что значительно не экономично, а если создавать огромный мод, то таких переменных, которые хранят только флаги будет множества, а я всегда люблю, когда по-меньше мусора и нудных переменных, которые хранят-лишь флаги. Этот способ имеет только один минус, дело в том, что мы не можем обозначить каждый бит переменной определенным именем, поэтому я взял маску состоящую всего из 8 битов (1 байт) от 0 до 255, то есть в одной переменной мы сможем хранить 8 флагов, конечно же можно было намного больше (4 байта - 32 бита), но тогда легко запутаться, какой бит отвечает за то или иное действие в режиме. Хочу показать пример, как обычно многие делают переменные, для хранения флагов: new flag[MAX_PLAYERS]; if(flag[playerid] == 1) SendClientMessage(playerid, 0x0, "Ваш флаг включён"); Здесь, помимо битов, можно сделать также оптимизацию, поставив тип bool либо char например: new bool: flag[MAX_PLAYERS]; if(flag[playerid] == 1) SendClientMessage(playerid, 0x0, "Ваш флаг включён"); Или: new flag[MAX_PLAYERS char]; if(flag{playerid} == 1) SendClientMessage(playerid, 0x0, "Ваш флаг включён"); С типом char получается даже экономичнее, чем с bool, потому что тип char это 1 байт, соответственно мы можем хранить значение без минуса от 0 до 255 - 8 бит, так как тип char в павн идет, как unsigned. Итак, синтаксис функций для управления и извлечения битов. Например создаем переменную для хранения 8 флагов, так как нам совершенно не нужно иметь целых 32 флага, мы будем использовать тип char, чтобы уменьшить их до нужного количество 8 бит, хотя ничего страшного не будет, если вы не будете использовать тип char, просто экономичнее использовать именно его в данном кейсе.
Синтаксис: фУНКЦИЯ: SetBitState(const bitid, &var, bool: status) (Изменяет бит в переменной): Аргументы: 1. bitid - айди (номер) бита начиная с нуля, максимально - 7 (всего 8). 2. &var - имя переменной, которой нужно изменить бит. 3. bool: status - новое значение бита (true (1) или false (0)). Функция ничего не возвращает.
фУНКЦИЯ: bool: GetBitState(const bitid, const var) (Получает значение бита переменной): Аргументы: 1. bitid - айди (номер) бита начиная с нуля, максимально - 7 (всего 8). 2. var - имя переменной, с которой нужно получить значение бита. Возвращает true (1) - если бит равен одному, иначе false (0), если бит равен нулю.
Примеры: Создадим массив для хранения 8 флагов всех игроков сервера, представим, что там находятся флаги вещей, которые имеет игрок. new items[MAX_PLAYERS char]; Допустим, игрок покупает какую-либо вещь, запишем её под нулевой бит, что она у него есть. SetBitState(0, items[playerid], true); А теперь проверим, если у него эта вещь: if(GetBitState(0, items[playerid])) SendClientMessage(playerid, 0x0, "Вы имеете эту вещь!");
Скорость выполнения: При 50000 итераций функции SetBitState - 19MS функции GetBitState - 16MS
Заключение: Конечно же этот способ в наши дни неактуален в силу того, что машины стали мощными, память уже давно не проблема, тем не менее я использую этот способ в некоторых местах, чтобы принципиально улучшить ситуацию, нежели создавать целых 8 переменных, которые в целом отвечают за один и тот же тип действия. Также этот способ может подойти для какого-нибудь кодирования данных, но в связи с тем, что в данном способе используется всего 8 бит, кодирование будет слишком простым и подобрать данные для него не составит никакого труда. P.S: Если кому-то интересно, могу выложить аналог этих функций в макросе, по-быстрее будет.
Русскоязычныи портал о MTA/GTA-IV-MP | http://multi-theft-auto.ru
Сообщение отредактировал toneysix - Суббота, 23.04.2011, 12:14
Кстати, текстовые строки (буквы и символы), разве выходят за пределы 0-255? А то тогда актуально вместо new string[128]; использовать new string[128 char]; ?
Ну почему же, можно его использовать, только умножая на два, все равно так или иначе тоже получится экономичнее, ведь всего к примеру для текста "текст" требуется 6x2=12 байтов, так например new string[6*2 char] = "текст"; будет корректным. С INT у нас получается одна ячейка 4 байта, поэтому объявляя таким образом: new string[6] = "текст"; получается 6x4=24, 24-12=12 байтов лишних.
Русскоязычныи портал о MTA/GTA-IV-MP | http://multi-theft-auto.ru
к примеру для текста "текст" требуется 6x2=12 байтов, так например new string[6*2 char] = "текст";
ну 1 байт лишний какбэ итак, исправлю: для текста "текст" требуется 5*2 = 10 байт (5 - кол-во символов, 2 - сколько байт на один символ(в юникоде нужно 2)) пример: new string[5*2+1 char] = "текст"; // 5*2 - будет создано 5 ячеек размерностью в 2 байта, +1 - ещё одна ячейка в 1 байт на завершающий символ (\n)(такая особенность унаследована у си++ )
ZZiGGi завершающий символ вообще-то \0 (нулевой символ), это первое, второе, у меня 6 символов с учетом этого нулевого байта, даже не смотря на то, что для него требуется 1 байт, в чем исправление вопрос?
Русскоязычныи портал о MTA/GTA-IV-MP | http://multi-theft-auto.ru
Сообщение отредактировал toneysix - Среда, 04.05.2011, 18:47