Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.06.2013, 09:38   #1
Gtnz8
Пользователь
 
Аватар для Gtnz8
 
Регистрация: 09.08.2012
Сообщений: 95
По умолчанию Указатель.

Код:
#include <stdio.h>
#include <stdlib.h>

int main()
{
    struct Ptrs
    {
        int *p1;
        int *p2;
    };
    struct Ptrs pointers;
    int i1=100;int i2;
    pointers.p1=&i1;
    pointers.p2=&i2;
    *pointers.p2= -  97;
    printf("i1 = %d *pointers.p1 = %d\n",i1,*pointers.p1);
    printf("i2 = %d *pointers.p2 = %d",i2,*pointers.p2);
    return 0;

}
Не могли бы объяснить почему оператор разыменования нельзя написать вот так
Код:
pointers.*p1= - 97;
?
Gtnz8 вне форума Ответить с цитированием
Старый 11.06.2013, 10:17   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Видимо разработчики Си решили что так удобнее. Вирт думал по другому. Билли впрочем походу тоже.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 11.06.2013, 11:17   #3
Shad0wF1rst
Форумчанин
 
Регистрация: 11.01.2013
Сообщений: 149
По умолчанию

Цитата:
Сообщение от Gtnz8 Посмотреть сообщение
Не могли бы объяснить почему оператор разыменования нельзя написать вот так
Код:
pointers.*p1= - 97;
?
Вы сами видите что запись сама по себе коряво выглядит. А с логической точки зрения ничего не меняется
Может это и чушь, но это моя чушь и я ее никому не отдам.
Shad0wF1rst вне форума Ответить с цитированием
Старый 11.06.2013, 11:21   #4
kventin_zhuk
БНТУ ФИТР
Форумчанин
 
Аватар для kventin_zhuk
 
Регистрация: 20.05.2012
Сообщений: 315
По умолчанию

Вполне логично - *.p2 - доступ к полю структуры, но какое дело компилятору что у вас поле структуры указатель? - это вы знаете что это указатель - поэтому и зарыменовываете как бы целиком
С++(console/builder/WinAPI/Linux), C#, Pascal, Delphi, Asm, Prolog.
< ----- Контакты
kventin_zhuk@live.com
kventin_zhuk вне форума Ответить с цитированием
Старый 11.06.2013, 11:40   #5
Gtnz8
Пользователь
 
Аватар для Gtnz8
 
Регистрация: 09.08.2012
Сообщений: 95
По умолчанию

Цитата:
Сообщение от kventin_zhuk Посмотреть сообщение
структуры, но какое дело компилятору что у вас поле структуры указатель? - это вы знаете что это указатель -
Прям ASM какой-то получается, о том что это число со знаком знает только программист.
Gtnz8 вне форума Ответить с цитированием
Старый 11.06.2013, 11:55   #6
revizor
Форумчанин
 
Аватар для revizor
 
Регистрация: 20.01.2013
Сообщений: 146
По умолчанию

а если поставить скобки, то такая запись становится более понятной )
Код:
cout << *(pointers.p1);
revizor вне форума Ответить с цитированием
Старый 11.06.2013, 12:06   #7
Gtnz8
Пользователь
 
Аватар для Gtnz8
 
Регистрация: 09.08.2012
Сообщений: 95
По умолчанию

Спасибо revizor, я и забыл совсем про такую запись.
Gtnz8 вне форума Ответить с цитированием
Старый 11.06.2013, 14:50   #8
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Gtnz8 Посмотреть сообщение
Не могли бы объяснить почему оператор разыменования нельзя написать вот так

Код:
pointers.*p1= - 97;
?
Потому что данный синтаксис уже используется с++ для других целей.

Кроме указателей на объекты классов, существуют так же ещё и указатели на члены этих классов.

И запись вида: obj.*member; //это доступ к членам класса, через указатель на член класса, для членов, которые являются data



Членами класса могут быть как data, так и method

Рассмотрим на детальном примере:

Код:
#include <iostream>
struct Some
{
   Some():mVal(333){}
   void View(){ cout<<" val = "<< mVal<<endl; }
   int mVal;
};

int main()
{
   //объявляю указатель на член класса:
   typedef int Some::* DataMember;

  //дословно: указатель на тип int, который живет в адресном 
  //пространстве класса Some


   //вот так создается и инициализируется объект такого указателя:
   DataMember dataMember = &Some::mVal;

   //вот так организуется доступ к члену класса, 
   //через указатель на член этого класса:

   //Тут нужно понимать, что доступ к членам класса возможен 
   //только если известен конкретный объект класса,
   // к полям которого мы обращаемся (необходимо знать this объекта):

   //для этого создадим объект к данным которого мы и обратимся
   Some obj;
   
   //а теперь через указатель на член изменим содержимое самого члена:
   //эквивалентна obj.mVal=20;
   obj.*dataMember = 20;  //<--- ничего тебе не напоминает?

   //здесь dataMember - указатель на член. 
   //И как для любого указателя, что бы получить содержимое 
   //по указателю  - его нада разыменовать. 
   //но так как таким указатели нуждаются в this объекта
   //то придумали вот такой синтаксис:

  //obj.*Member; //доступ к члену через объект
  //obj->*Member; //доступ к члену через указатель на объект



   //Однако, мы всегда можем перенацелить указатель на другой член 
   //класса такого же типа, и через указатель изменить уже другой член


   //Теперь создадим указатель на метод класса: void Some::View
   typedef void (Some::*FuncMember)();

  //Примичание: запись вида void() обозначает тип функции
  //Дословно: указатель на функцию с типом void(), 
  //которая живет в адресном пространстве класса Some

   //нацеливаемся на метод класса
   FuncMember funcMember = &Some::View;

   //а теперь запускаем метод класса через указатель:
    (obj.*funcMember )(); //эквивалент obj.View();

   //через указатель, вы можете запускать любые методы класса, 
   //для которых совпадает тип указателя на метод

  return 0;
}
С непривычки синтаксис может показаться замороченным. На самом деле он довольно простой и логичный.

Все что нужно - это уметь правильно расставлять приоритеты операций.

Так допустим, твой случай на самом деле это операция вида:
Код:
*(pointers.p1);
Сначала делаем доступ к члену класса по имени, а потом разыменовываем его.

Теперь понимаешь?

Что бы проверить самого себя, насколько хорошо ты это понимаешь, выполни следующее упражнение:

Код:
int gValue= 10;
struct Some
{
   Some():ref(gValue){ for(size_t n=0;n<10;++n) arr[n]=333; }
   int arr[10];
   int& ref
};

int main()
{
   //через указатели на члены,
   //1. Требуется получить доступ к Some::arr, 
   //и сделать всего его элементы равным 1

   //2. Требуется получить доступ к Some::ref
   //и изменить содержимое на число 333

   return 0;
}
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передать указатель на указатель в функцию erro Общие вопросы C/C++ 3 29.10.2012 17:59
указатель Don Karleone Общие вопросы Delphi 10 23.05.2012 13:36
указатель this Madmaxisss Visual C++ 7 25.07.2011 23:31
Указатель RobinVit Помощь студентам 3 05.05.2010 16:18
(!)указатель на указатель(!) (C)stalin(Cpp) Общие вопросы C/C++ 0 07.06.2009 15:32