Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатели и ссылки в C++: нюансы, ВНИМАНИЕ!!! Новичкам не читать! 
:(
    Опции темы
feodorv
Дата 2.12.2013, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



NoviceF, как насчёт
Код

int* x, y;

???


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
EgoBrain
Дата 2.12.2013, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



feodorvNoviceF, понеслось из пустого в порожнее, это уже обсуждалось на первых страницах.
Bsa, да ты я смотрю любишь глумиться чтоле? это я по поводу закрытия темы, давно пора уж 
PM MAIL ICQ Skype   Вверх
vinter
Дата 2.12.2013, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



feodorv, а так писать не надо. Одна строка - одна инициализированная переменная.


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 2.12.2013, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



maxi2
ответьте на вопросы, что означает
1.
Код

int *x;

2. 
Код

*x;

3. (само по себе и в контексте объявления выше)
Код

x; 

4.
Код

&x;

5.
Код

int &y;

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

****p; 

можно рассматривать как *(*(*(*p))); а по отдельности вы знаете. больше никаких сложностей здесь нет, вы сами себе все усложняете
PM MAIL   Вверх
nubliK
Дата 2.12.2013, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


вселенские матрицы



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 11.9.2008
Где: Владивосток

Репутация: нет
Всего: нет



Попробую объяснить для maxi2 как все работает. Приведу такой код, желательно чтобы maxi2 скомпилировал его и посмотрел что получается.


Код

#include <iostream>
#include <conio.h>
using namespace std;

void main(){
    int p;
    float f;
    char ch;
    double d;
    

    p=15; f=15; ch='a'; d=5;

    int *p_ptr=&p;
    float *f_ptr=&f;
    char *ch_ptr=&ch;
    double *d_ptr=&d;

    cout << "int " << sizeof(int) << endl;
    cout << "char " << sizeof(char) << endl;
    cout << "double " << sizeof(double) << endl;
    cout << "float " << sizeof(float) << endl << endl;

    cout << "ptr_int " << sizeof(*p_ptr) << endl;    
    cout << "ptr_char " << sizeof(*ch_ptr) << endl;
    cout << "ptr_double " << sizeof(*d_ptr) << endl;
    cout << "ptr_float " << sizeof(*f_ptr) << endl << endl;
    
    cout << "link_int " << sizeof(&p) << endl;    
    cout << "link_char " << sizeof(&ch) << endl;
    cout << "link_double " << sizeof(&d) << endl;
    cout << "link_float " << sizeof(&f) << endl << endl;

    cout << "link_int_var " << &p << endl;    
    cout << "link_char_var " << &ch << endl;
    cout << "link_double_var " << &d << endl;
    cout << "link_float_var " << &f << endl << endl;

    cout << "ptr_int_var " << *p_ptr << endl;    
    cout << "ptr_char_var " << *ch_ptr << endl;
    cout << "ptr_double_var " << *d_ptr << endl;
    cout << "ptr_float_var " << *f_ptr << endl << endl;

    cout << "int_var " << p << endl;    
    cout << "char_var " << ch << endl;
    cout << "double_var " << d << endl;
    cout << "float_var " << f << endl;

    

    _getch();
}


Теперь по порядку:

1 - память в компьютере представляет из себя плоскую модель, сделано это для простоты, при этом как на самом деле устроенная физически память нас мало интересует. что есть плоская модель? - это когда у тебя конкретное содержимое ячейки памяти соответствует одному и только одному собственному адресу. Адрес и ячейка памяти это две большие разницы и хранятся они по разному.

2 - что такое ссылка? это адрес памяти в которой что то хранится (переменная, класс, функция и т.д.), НО везде пишется что это ссылка ссылается на адрес чего то. Ссылка записывается так &ЧТОТО, под ЧТОТО - понимается переменная, то есть вот это "ЧТОТО" - это есть псевдоним переменной, а запись &ЧТОТО - это есть ссылка на то самое ЧТОТО, то есть уже не псевдоним а конкретно на значение.

Вот память:

| тут адреса | тут значения |
|----------------|-------------------|
|адрес №1    | ЧТОТО            |
|----------------|-------------------|
|адрес № 2   | ЧТОТОЕЩЕ    |
и так далее от начала до конца (памяти для программы, не физической памяти).

Конструкция &ЧТОТО - в памяти компьютера хранится как адрес и занимает в этой памяти (на процессорах х86) 4 байта.

3 - что такое указатель? - это переменная хранящая адрес другой переменной в памяти. Почему указатель тоже переменная? потому что с ним тоже можно производить арифметические операции. Что физически представляет конструкция например int * p = &p - читается как указатель на переменную типа ИНТ, само выражение называется "РАЗЫМЕНОВАНИЕМ" то есть - есть ссылка в памяти представленная как &p и есть указатель на какую то ссылку int * p, когда компилятор встречает такое &p он говорит что "я линкёру передам адрес переменной p" при этом память под хранение ссылки &p не выделится а будет связь между переменной p и ее адресом &, далее компилятор встречает вот это int *p и что он делает? он говорит операционной системе, "выдели пожалуйста память для хранения адреса какой то переменной (пока мы не знаем какой) но переменная будет типа ИНТ". Далее компилятор читает выражение дальше и встречает оператор присваивания =, (наше выражение приобретает вид int * p = &p) и говорит - "линкёр, линкёр свяжи ссылку типа переменной p типа ИНТ с выделенным адресом под указатель типа инт". После этой операции с *p - можно обращаться как с переменной p без зазрения совести. И называться *p будет указателем на p типа ИНТ.

Это сложно понять с первого раза, причем всем. В нашем случае важна другая суть. Суть в том что указатель на переменную дает возможность работать с этой переменной на прямую не делая копию этой переменной. Указатели можно складывать, умножать, вычетать и т.д.

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

Различия между С++ и С: в си ссылочная арифметика вызовет предупреждение, в си плюс плюс такая арифметика вызовет ошибку.

(а может я не прав? поправьте меня если где то ошибся)  smile 

Для maxi2 попробуй прибавить еденицу в програме выше к указателю и к ссылке и выведи себе результат в консоль. поэксперементируй.
PM MAIL ICQ   Вверх
baldina
Дата 2.12.2013, 10:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(NoviceF @  2.12.2013,  08:14 Найти цитируемый пост)
её можно понять, как 2 лексемы

её нужно понять как 3 лексемы, а дальше включать контекст. синтаксис с++ не слишком дружествен, что поделать...
PM MAIL   Вверх
maxi2
Дата 2.12.2013, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.5.2012

Репутация: 1
Всего: 1



Вы уже не обьясняйте о указателях. Вот двойной это действительно непонятно пока что. Ведь в примере где x=1, *y, **z, ***k все они если втыкнуть в СИ-аут будут равны 1. То что **р=*(*p) я и сам спрашивал. По ходу понял что синтаксис обьявиение синтаксиса как раз не искусственный ибо int *p=&х-надо воспринимать как int*  p=&х; тогда станет понятно почему указатель p равен адресу переменной как должно быть. Тут дело в том что int *p воспринимается как значение что есть в указателе то есть его разименование. То есть например если мы обьявим переменную int х=5; и если есть такой адрес памяти с таким адресом памяти как 0х5 то вызов значение в таком адресе если оно есть *х (например 2500) при присваивание его другой переменой int y=*х или cout<<*х вызовет ошибку ибо в таком случае надо было х обьявлять с типом int*. Если так то действительно это было ошибкой с моей стороны.
PM MAIL   Вверх
xvr
Дата 2.12.2013, 12:23 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(maxi2 @  2.12.2013,  12:05 Найти цитируемый пост)
Если так

Именно.

 smile 

Цитата(maxi2 @  2.12.2013,  12:05 Найти цитируемый пост)
и если есть такой адрес памяти с таким адресом памяти как 0х5 то вызов значение в таком адресе если оно есть *х (например 2500)

Я тихо шизею с авторского стиля изложения  smile  smile  smile 

PM MAIL   Вверх
nubliK
Дата 2.12.2013, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


вселенские матрицы



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 11.9.2008
Где: Владивосток

Репутация: нет
Всего: нет



Цитата(maxi2 @ 2.12.2013,  12:05)
Тут дело в том что int *p воспринимается как значение что есть в указателе то есть его разименование. То есть например если мы обьявим переменную int х=5; и если есть такой адрес памяти с таким адресом памяти как 0х5 то вызов значение в таком адресе если оно есть *х (например 2500) при присваивание его другой переменой int y=*х или cout<<*х вызовет ошибку ибо в таком случае надо было х обьявлять с типом int*. Если так то действительно это было ошибкой с моей стороны.

Что есть в указателе то есть значение переменной по адресу.

Типы данных должны соответствовать друг другу. Компилятор не знает других типов кроме примитивных, а как обращаться с типами вне стандартного набора, компилятору надо объяснять.
PM MAIL ICQ   Вверх
nubliK
Дата 2.12.2013, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


вселенские матрицы



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 11.9.2008
Где: Владивосток

Репутация: нет
Всего: нет



Пример от baldina тоже простой

Код

        int x=1;
    int *px=&x;
    int **ppx=&px;
    int ***pppx=&ppx;
    cout << ***pppx; // prints 1


А что тут сложного maxi2?

По аналогии int x = 1; инициализация переменной
                     &x - ссылка на переменную x
                     int *px указатель на х
                     &px - ссылка на ячейку где хранится адрес переменной x
                     **ppx - указатель указателя на х
                     и т.д.
PM MAIL ICQ   Вверх
maxi2
Дата 6.12.2013, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.5.2012

Репутация: 1
Всего: 1



Да и с логикой двойных и более указателей разобрался. То есть от указателя верхнего уровня идет разименование к указателям с меньшим числом  звездочек. Но как там быть с трехмерном масивом как под него выделять память с помощью указателей. Было однажды у меня такое задание. А в нете какого то примера именно с учебников нету. Только вот такое обьявиение конструктора не совсем понятно : Student (char* name="popov"). Ну тогда name это ведь адрес переменной сивольного типа? Ведь скорее мы на примере целоч. типа мы б имели char x="popov"; char* name=&x; 2. Чтобы не создавать новые темы задам здесь два микровопроса по C++: 1)есть ли разница в быстродействие между пре- и пост-инкрементом(один из вариантов был что пре-и. есть быстрее или тот же сам по  скорости)2. Потом был у меня тест о S tack и heap-памяти: то наиболее подходящий вариант звучал как то что стек память касается локальных переменных, а Хип-выделение динамической памяти. Соответствует ли это действительности, ибо иные варианты были вообще никудышние. 
PM MAIL   Вверх
xvr
Дата 7.12.2013, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(maxi2 @  6.12.2013,  19:54 Найти цитируемый пост)
Но как там быть с трехмерном масивом как под него выделять память с помощью указателей. 

Так же, как и 2х мерным. Каждый уровень указателя требует вложенного цикла и new в нем:
Код

int ***arr = new int**[N3];
for(int i=0;i<N3;++i)
 {
   arr[i]=new int*[N2];
   for(int j=0;j<N2;++j)
    arr[i][j]=new int[N1];
 }


Цитата(maxi2 @  6.12.2013,  19:54 Найти цитируемый пост)
Только вот такое обьявиение конструктора не совсем понятно : Student (char* name="popov").

Это описание значения по умолчанию. Если вы напишите Student(), то реально будет вызвано Student("popov")

Цитата(maxi2 @  6.12.2013,  19:54 Найти цитируемый пост)
Ну тогда name это ведь адрес переменной сивольного типа?

Не только. В языке С (и С++) указатель может указывать как на отдельную переменную, так и на массив (что иногда приводит к путанице). В данном случае указатель используется в смысле указателя на массив символов. В "popov" - это и есть массив символов (так устроены строковые константы в С)

Цитата(maxi2 @  6.12.2013,  19:54 Найти цитируемый пост)
Соответствует ли это действительности

Если речь идет именно о переменных, то да.

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0949 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.