Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 2 из 2
  1. #1
    Аватар для Tracker1
    Проверенный

    Статус
    Оффлайн
    Регистрация
    30.07.2013
    Сообщений
    54
    Репутация:
    84 ±

    [Цикл уроков программиста] 11. Структуры, объединения, перечисления

    Сегодня мы рассмотрим три совершенно невзаимосвязанные темы: структуры, перечисления и объединения. Так как они не слишком сложные, мы рассмотрим их все вместе.
    Структуры (struct)
    Использование структур обусловлено необходимостью объединить несколько переменных.

    Структуры - это, обычно, группа переменных описывающих какую-нибудь сущность.

    Например, в игре танк можно описать группой переменных: количество снарядов, количество горючего и т.д. У нас в примере танк будет обладать следующими параметрами: координаты и количество топлива (от нуля до двадцати).

    Зачем нам использовать какие-то структуры спросите Вы? Ведь переменные и так прекрасно хранятся.

    Причин две: переменные в структурах хранятся в одном месте и можно создавать несколько структурных переменных и у всех у них будут одинаковые характеристики.

    Объявления у структуры нет. Её нужно сразу определять. Тело структуры должно находиться до начала main.

    PHP код:
    struct tank
    {
      
    int xy;
      
    int fuel;
    }; 

    Здесь мы видим структуру с именем tank. Перед именем стоит ключевое слово struct (от structure - структура). В теле структуры находятся объявления переменных отвечающих за координаты и кол-во топлива. Обратите внимание, что после закрывающей фигурной скобки стоит точка с запятой. Не забывайте о ней в своих структурах.

    На самом деле мы только что создали новый тип данных. Такие типы данных - определяемые программистом, называются пользовательскими. К пользовательским типам данных, помимо структур, относятся и классы, но об этом в следующий раз.
    Когда мы определяем структуру, под неё не выделяется память. Структура - это как шаблон. Теперь на основе структуры tank можно создать много структурных переменных. Все эти переменные будут иметь тип tank, и каждая структурная переменная будет иметь доступ к своим переменным x, y, fuel.

    Сейчас нам нужно определить переменную типа tank. Или даже две:
    PHP код:
    tank t34 = {0,0,20}; // x, y, fuel
    tank pz4 = {8,7,20}; 

    Обе переменные мы сразу проинициализировали (хотя этого можно было и не делать). Для этого использовали список значений в фигурных скобках. Значения в скобках присваиваются переменным внутри структуры в том порядке, в котором они были объявлены при определении структуры: x, y, fuel.

    Теперь у нас есть две переменные t34, pz4 типа tank. У каждой есть поля x, y, fuel. Подчёркиваю красным: каждая структурная переменная обладает своим набором переменных, которые были объявлены в структуре.

    Чтобы получить доступ к полю, нужно воспользоваться операцией доступа (операцией точки). Например:

    PHP код:
    pz4.fuel 100;
    cout << pz4.fuel << "\n"
    Сначала мы указываем имя структурной переменной, затем ставим точку и в конце указываем имя поля структуры. Здесь мы присвоили значение полю fuel структурной переменной pz4, а затем вывели значение поля fuel на экран.

    Напоследок, вот как получить доступ ко всем полям двух структурных переменных:

    PHP код:
    t34.x;
    t34.y;
    t34.fuel;
    pz4.x;
    pz4.y;
    pz4.fuel
    Структурные переменные в памяти компьютера

    А вот как структурные переменные располагаются в памяти компьютера (адреса в шестнадцатиричном формате):



    Каждая переменная типа int занимает в памяти четыре байта. Вся структурная переменная структуры tank займёт в памяти 12 байт - три переменные типа int.

    Адрес переменной - младший байт этой переменной. Например, адрес переменной t34.fuel - 0012FEA2.

    Кроме того стоит заметить, что адрес самой стуктурной переменной t34 совпадает с адресом первого поля x. Т.е. адрес t34.x равен 0012FE94, адрес t34 равен 0012FE94.

    Также обратите внимание, что все поля t34 расположены друг за другом. Заканчивается переменная x (адрес 0012FE97) и следующий байт уже принадлежит y (0012FE98), заканчивается y (адрес 0012FEA1) и сразу же начинается fuel (адрес 0012FEA2). Запомните, поля структурной переменной хранятся в памяти друг за другом, между ними нет никаких других данных.

    И ещё одно, две структурные переменные t34 и pz4 необязательно расположены в памяти рядом. В данном примере между ними больше 140-а байтов. Кроме того, переменная pz4 расположена в памяти "раньше" - адрес этой переменной меньше адреса t34.

    Хорошенько разберитесь со всем этим. Когда дойдём до рассмотрения указателей, вы поймёте, зачем необходимо понимание того, как устроена память.
    Перечисления (enum)

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

    С помощью перечислений можно задать дни недели, месяцы, ну или что-нибудь подобное. В качестве примера рассмотрим стороны света. Стороны света на экране расположены так: вверху - север (north), справа - восток (east), слева - запад (west) и внизу - юг (south).

    PHP код:
    enum cardinal_dirs northwesteastsouth }; 
    Здесь мы определили перечисление cardinal_dirs. В начале строки стоит ключевое слово enum (enumeration - перечисление). Затем указывается имя перечисления, после которого, через пробел, в фигурных скобках задаются значения, которые смогут принимать переменные типа cardinal_dirs. После фигурных скобок ставится точка с запятой.

    После того, как определено перечисление, можно создавать переменные нового типа:

    PHP код:
    cardinal_dirs ch north
    Обратите внимание, что переменные типа cardinal_dirs могут принимать только четыре значения: north, south, east, west. Кроме того, элементы в перечислении нумеруются от нуля. Т.е. north = 0, east = 1, south = 2, west = 3. Вместо перечисления мы могли бы создать четыре константы:
    PHP код:
    const int north 0;
    const 
    int east 1;
    const 
    int south 2;
    const 
    int west 3
    Результат одинаковый.

    Как видите использовать перечисления довольно легко. Но стороны света у нас закодированы клавишами стрелочек, поэтому нам нужно инициализировать элементы перечисления числами. Как я уже писал, отсчёт ведётся с нуля. Но, к счастью, это можно изменить. Если мы переопределим какой-либо элемент значением 75, то следующий, получит значение 76. Нам нужно переопределить все четыре значения.

    PHP код:
    enum cardinal_dirs north 72west 75east 77south 80 }; 
    Про структуры и перечисления всё. Есть ещё некоторые важные моменты по структурам, но нам они пока не нужны.

    Ещё раз повторюсь, точно такого же результата можно было бы добиться с помощью четырёх констант.
    Объединения (union)

    Объединения используются когда необходимо получить доступ к одним и тем же данным разными способами.

    Допустим мы хотим вывести все поля структуры tank. Пока что у нас есть только один способ сделать это:
    PHP код:
    cout << t34.<< "\n";
    cout << t34.<< "\n";
    cout << t34.fuel << "\n"

    Гораздо удобнее это было бы сделать с помощью цикла. Но тогда нам пришлось бы использовать массив, а определение структуры выглядело бы вот так:

    PHP код:
    struct tank
    {
      
    int t[3];
    }; 

    Теперь вывести структурную переменную на экран проще:
    PHP код:
    for (int i3i++)
    {
      
    cout << t34.t[i] << "\n";


    Но при использовании массивов переменная потеряла в гибкости, и код стал не таким понятным:

    PHP код:
    t34.3// До..
    t34.4;

    t34.t[0] = 3// ... и после.
    t34.t[1] = 4

    Можно объединить эти два способа с помощью объединения. :)

    При этом структура tank будет выглядеть вот так:

    PHP код:
    union tank
    {
      
    struct
      
    {
        
    int x,y;
        
    int fuel;
      };
      
    int t[3];
    }; 

    Во-первых мы заменили struct на union (union - объединение). Внутри объединения расположена безымянная структура в которой определены все те переменные, которые были в структуре tank.

    После безымянной структуры определён массив целых чисел из трёх элементов.

    Теперь создадим переменную и обратимся к её полям:
    PHP код:
    tank t34;

    t34.5;
    t34.1;
    t34.fuel 20;

    cout << t34.t[0] << "\n";
    cout << t34.t[1] << "\n";
    cout << t34.t[2] << "\n"
    На экран будет выведено:
    Код:
    5
    1
    20
    Дело в том, что x и t[0] - разные имена одного и того же участка памяти, также как и: y и t[1], fuel и t[2].

    Вот как переменная типа tank расположено в памяти:



    union tank имеет тот же адрес, что и x и t[0], просто у нас картинки рисует чрезвычайно толковый парень, поэтому получается так.

    На картинке перед каждым адресом стоит: 0x (ноль икс). Это обозначение используется с шестнадцатиричными числами, т.е. если перед числом вы увидите 0x - то оно представлено в шестнадцатиричном формате.

    А что будет если не определять безымянную структуру, а переменные располагать следующим образом:

    PHP код:
    union tank
    {
      
    int x;
      
    int y;
      
    int fuel;
      
    int t[3];
    }; 
    Ничего хорошего из этого не выйдет. Здесь x, y, fuel и t[0] - имена одного участка памяти.

    В будущем мы будем использовать объединения следующим образом:
    PHP код:
    struct tank
    {
      
    union
      
    {
        
    struct
        
    {
          
    int x,y;
          
    int fuel;
        };
        
    int t[3];
      };
    }; 
    Но вместо слово struct в первой строке будет стоять class. Сейчас вот этот вариант (struct tank) и предыдущий (union tank) работают одинаково.

    Применение объединений очень сильно ограничено. Мы их рассмотрели, так как они особенно часто встречаются в математических библиотеках.
    Последний раз редактировалось bredvix; 25.02.2014 в 18:02.

  2. Пользователь сказал cпасибо:
    vovandolg (16.10.2016)
  3. #2
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,369
    Репутация:
    113 ±
    Не хватает буквы С
    Код:
    Например, адрес переменной t34.fuel - 0012FEA2.
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

 

 

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

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

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

Ваши права

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