Пятница, 17.11.2017, 23:06
Приветствую Вас Гость | RSS

Кузница миров

Меню сайта
Категории раздела
Мои статьи [2]
Курс : "Основы С++ для начинающих программистов игр." [25]
WindMill Engine [3]
XNA4 RPG [0]
Перевод туториалов но созданию RPG на C# c XNA4.
C# & Leadwerks [5]
Программирование Leadwerks Engine на языке С# с помощью врапера Le.NET.

Каталог статей и уроков

Главная » Статьи » Курс : "Основы С++ для начинающих программистов игр."

4.6. Указатели
4.6. Указатели


На этой лекции я решил подвести черту под типами данных. Поэтому настала очередь рассказать еще об одном – об указателях. Этот тип данных является чем то вроде камня преткновения в языке программирования С++. Благодаря указателям программы приобретают необычайную гибкость и непревзойденную скорость, но благодаря им же появляются многочисленные серьезные, трудно ловимые баги и ошибки.
Итак, указатель это переменная, хранящая в себе адрес другой переменной. Чтобы понять, что я имею ввиду нужно знать, что значит адрес переменной.

Адрес

Как вы уже знаете, память компьютера состоит из битов, которые в свою очередь собраны в байты. У каждого байта имеется свой адрес, представленный в виде шестнадцатеричного числа.
Каждая переменная занимает в памяти от одного до нескольких байтов. Так вот, адресом переменной становится адрес ее первого байта.

Чтобы получить адрес переменной используется оператор взятия адреса - &.
Этот оператор нам уже попадался под видом битового И. Теперь же с его помощью мы будем получать адрес. Действие, которое этот оператор выполняет, зависит от способа его записи. Если он стоит между двумя переменными то это И, если он стоит перед одной переменной то это оператор взятия адреса. Операторы которые применяются всего к одной переменной называются унарными.

Использование указателей.

Как получить адрес, мы уже знаем. Теперь познакомимся с синтаксисом объявления указателя.

Code
тип_данных      *имя_переменной


Здесь ключевую роль играет унарный оператор звездочка *. С помощью которого переменная и становится указателем. Как и при объявлении других переменных, здесь также есть тип данных. Здесь указывается тип данных переменной, на которую ссылается указатель.
Пример

Code
    int i=1564;       int *pi;    // обьявление указателя       pi = & i;    // взятие адреса


пример можно сократить

Code
    int i=1564;       int *pi= & i;    // обьявление указателя и взятие адреса


Здесь в имени указатели, согласно венгерской нотации, используется префикс p. Чтобы не запутаться в своей программе и знать что переменная это указатель, советую вам использовать его всегда.
Теперь напишем небольшую программу, которая выдаст нам адреса нескольких переменных.

Code
#include <iostream>  using namespace std;    void main()  {        setlocale(0,"");       int s=50;       int i=456;       double d=4.1456;         int *ps = &s;       int *pi = &i;       double *pd = &d;         cout<<"адрес переменной s "<<ps<<'\n';       cout<<"адрес переменной i "<<pi<<'\n';       cout<<"адрес переменной d "<<pd<<'\n';         cin.get();       cin.get();    }  


Хорошо, объявлять и присваивать адрес указателю мы научились. Но как получить значение, хранящееся по определенному адресу. Для этих целей используется оператор разыменования указателя, и это все та же звездочка *.

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

Code
    cout<<"\nзначение переменной по указателю ps "<<*ps<<'\n';       cout<<"значение переменной по указателю pi "<<*pi<<'\n';       cout<<"значение переменной по указателю pd "<<*pd<<'\n';  

Все просто.
С помощью разыменования указателя можно не только получить, но и изменить значение переменной. Делается это так:

Code
int i=456;  int *pi = &i;  *pi = 30;


Понять запись можно так. Вначале с помощью звездочки мы обращаемся к значению и присваиваем ей новое. Пример кода будет дальше.
Теперь я приведу пример неосторожного использования указателей. Вот что случится, если случайно, посредством указателей, присвоить переменной с типом int значение с типом double:

Code
#include <iostream>  using namespace std;    void main()  {        setlocale(0,"");       int s=50;       int i=456;       int a=785;         cout<<"s "<<s<<'\n';       cout<<"i "<<i<<'\n';       cout<<"a "<<a<<'\n';         double *pd = (double*)&i;       *pd = 13.4568;         cout<<"s "<<s<<'\n';       cout<<"i "<<i<<'\n';       cout<<"a "<<a<<'\n';         cin.get();       cin.get();  }  

Здесь
Code
*pd = 13.4568;


Присваивание значения через указатель.
В этой программе есть непонятная нам строка.

Code
    double *pd = (double*)&i;


а конкретно (double*)&i.

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

Code
int i = (int)3.14;    // преобразовываем float в int  int i = (int)'a';    // char в int  char c = (char)100; // и наоборот  


В некоторых случаях программа может делать преобразования самостоятельно (неявное преобразование). А иногда, как и в примере с указателями, это нужно делать вручную, иначе компилятор выдает ошибку.
Но вернемся к нашему примеру, что же будет в результате присваивания int значения double.
Первое - значение переменной будет некорректным. Второе – при работе программы возникнет ошибка, связанная с порчей памяти, как и в примере с массивами.

Что ж, думаю на этом со знакомством с указателями можно завязывать. Но мы к ним еще не раз вернемся. Позже мы узнаем, зачем же они нужны и сможем раскрыть всю их мощь.

Послесловие


Ну и как обычно пару слов на конец.
Лекция была сложной, и содержала много новой информации. Поэтому вам еще не раз придется к ней возвращаться. Большая часть сведений вам пока не понадобится, разве что для общего понимания. Преобразования систем счисления, манипуляция с битам нужна только в особых случаях. А вот знания про массивы и указатели будут нужны постоянно.
Я надеюсь, что вы прочитали и поняли все, но если что-то пропустили или не совсем поняли, ничего страшного. Можно прочитать и пройтись по примерах еще раз, при этом особое внимание уделяя как раз массивам и указателям.
Ну и если что, спрашивайте.
На этом все, до встречи.

ЗЫ: Я надеюсь, что вас не напугали возникшие сложности, и мы еще встретимся. Ведь так?
Категория: Курс : "Основы С++ для начинающих программистов игр." | Добавил: nilrem (11.05.2012)
Просмотров: 470 | Рейтинг: 1.0/1
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0