10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
1

Указатель на указатель - разница способов

14.03.2010, 14:18. Показов 1825. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
int a =5;
int *b = &a;
 
 
 
int **e =&b;  //первый способ
//Нужно писать столько * скока указателей..
 
 
int *f = b; //Втрой способ
второй проще..
зачем тогда есть первый?

и как сделать укзатель на указатель на указатель?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.03.2010, 14:18
Ответы с готовыми решениями:

Указатель или ссылка на указатель. В чем разница?
Есть вопрос про указатели и ссылки на указатели :scratch: Хочу в функциях f1() и в f2()...

Как получить ссылку на указатель или указатель на указатель в массиве?
В процессе реализации сортировки пузырьком натолкнулся на такую проблему: как поменять значения...

А почему нельзя передавать в ф-ю добавления элемента в стек один указатель? Почему нужен именно указатель на указатель?
Вот код ф-ии добавления элемента в стек: void push1(Node **top, int d) { // top...

Итератор и указатель в чем разница
Здравствуйте, Подскажите пожалуйста, вот есть такое определение: Для получения итераторов...

18
Псевдо программист
192 / 113 / 37
Регистрация: 19.09.2009
Сообщений: 303
14.03.2010, 14:26 2
Krist_ALL, "второй способ" это не указатель на указатель, я присвоить значению указателя f значение b

первый способ единственный
0
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
14.03.2010, 14:43  [ТС] 3
C++
1
2
3
4
int **e =&b; //5
 
 
int *f = b; //5
0
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
15.03.2010, 14:57  [ТС] 4
int a = 5;

Первый способ
int *b = &a;
int *c = b;
int *d = c;

ВТорой

int *b = &a;
int **c = &b;
int ***d = &c;

первый ведь удобнее.
и не надо тучу * писать..
или я не прав?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 15:11 5
Лучший ответ Сообщение было отмечено как решение

Решение

Ты не прав. Это два разных способа, и используются они в разных случаях (конечно же, в твоем случае второй способ не используется, как нерациональный)
Первый способ. Ты объявляешь целую переменную a, потом объявляешь указатель b на целый тип, и инициализируешь его адресом a (с помощью операции взятия адреса). Теперь в переменной b хранится адрес a. Потом ты объявляешь еще один указатель c на целый тип, и инициализируешь его не адресом указателя b, а значением, которое он хранит-адресом а. Остальные указатели объявляются и инициализируются аналогично. Теперь, чтобы получить доступ к значению, которое храниться в a, например, с помощью указателя b, тебе нужно совершить однократную операцию разыменования указателя(например, *b=19 - и в переменной a будет храниться уже значение 19).
Второй способ. c - это уже указатель на указатель на целый тип, и он хранит уже не адрес a, а адрес указателя b. Соответственно, d - это указатель на указатель на указатель на целый тип, и чтобы изменить значение a с помощью указателя d, тебе нужно применить три раза операцию разыменования (***d=19). (*d==c==&b==&&a, **d==b==&a, ***d==a - это для наглядности )
PS. Здесь и ответ на твой вопрос:
Цитата Сообщение от Krist_ALL Посмотреть сообщение
и как сделать укзатель на указатель на указатель?
2
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
15.03.2010, 15:23  [ТС] 6
Это я понимаю)
ав каких случаях первый способ рационален а когда второй.
в каких ситуациях?
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
15.03.2010, 15:26 7
Цитата Сообщение от Krist_ALL Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
int a =5;
int *b = &a;
 
 
 
int **e =&b;  //первый способ
//Нужно писать столько * скока указателей..
 
 
int *f = b; //Втрой способ
второй проще..
зачем тогда есть первый?

и как сделать укзатель на указатель на указатель?
Сделай printf ("%d", **e); и printf ("%d", **f);
Увидишь, что второй код - вовсе не то, что ты думал

Добавлено через 1 минуту
Цитата Сообщение от Krist_ALL Посмотреть сообщение
ав каких случаях первый способ рационален а когда второй.
Второго способа нет, потому как он делает совсем не то
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 15:27 8
Evg, ну я же написал - для наглядности
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
15.03.2010, 15:28 9
Цитата Сообщение от Nameless One Посмотреть сообщение
Evg, ну я же написал - для наглядности
Я понял, но не сразу Удалил
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 15:44 10
Цитата Сообщение от Krist_ALL Посмотреть сообщение
ав каких случаях первый способ рационален а когда второй.
Вопрос не в том, когда рационален один способ, а когда второй. Они используются для разных целей.
Начнем с того, что в C/C++ массивы реализованы с помощью указателей:
C++
1
2
int a[5];//a - указатель на первый элемент массива
         //a+1 - указатель на второй элемент массива и т.д.
Таким образом, записи a[0] и *(a+0), a[4] и *(a+4) - аналогичны. Когда ты используешь многомерные массивы (т.е. с размерностью больше единицы), ты уже используешь указатели на указатели на указатели... К примеру, двумерный массив типа int - это указатель на указатель на тип int.
Без указателей на указатели не обойтись, если ты хочешь динамически выделить память под многомерный массив:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
int main()
{
    //Выделение памяти под двумерный массив
    int** parr=new int*[2];
    for(size_t i=0; i<2; ++i)
    {
        parr[i]=new int[2];
        for(size_t j=0; j<2; ++j)
            parr[i][j]=i+j;//Доступ по индексу
    }
    for(size_t i=0; i<2; ++i, std::cout << std::endl)
        for(size_t j=0; j<2; ++j)
            std::cout << *(*(parr+i)+j) << " ";//Доступ через операцию разыменования
    //Освобождение памяти
    for(size_t i=0; i<2; ++i)
        delete[] parr[i];
    delete[] parr;
    system("pause");
    return 0;
}
Сначала ты выделяешь память под массив строк, потом для каждой строки ты выделяешь память под массив ее элементов
0
1261 / 799 / 108
Регистрация: 16.09.2009
Сообщений: 2,010
15.03.2010, 15:57 11
Двойной указатель используется для передачи простого указателя по адресу.
Могу не большой пример привести: добавление на вершину стека:
C++
1
2
3
4
5
6
void push(Node **top,int d){
Node *p = new Node;
p->d=d;
p->next=(*top);
(*top)=p;       //в переданном указателе меняется значение: теперь он ссылается на другую память.
}
Здесь передается указатель на вершину стека, его значение(указателя) меняется в этой функции.
1
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 16:06 12
Genius Ignat, пример, конечно, наглядный, но что нам мешает передавать не адрес указателя, а сам указатель, и не применять лишних операций разыменования?
0
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
15.03.2010, 17:14  [ТС] 13
а как передавать не адрес указателя, а сам указатель?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 17:18 14
C++
1
2
3
4
5
6
void push(Node *top,int d){
Node *p = new Node;
p->d=d;
p->next=top;
top=p;       
}
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
15.03.2010, 18:02 15
Цитата Сообщение от Krist_ALL Посмотреть сообщение
а как передавать не адрес указателя, а сам указатель?
C
1
2
3
4
5
6
7
8
9
10
11
/* Передача указателя */
extern void func (int *p);
...
int *ptr;
func (ptr);
 
/* Передача адреса указателя */
extern void func (int **p);
...
int *ptr;
func (&ptr);
1
1261 / 799 / 108
Регистрация: 16.09.2009
Сообщений: 2,010
15.03.2010, 21:11 16
Лучший ответ Сообщение было отмечено как решение

Решение

Nameless One:
Ты ошибаешься, это уже не добавление на вершину стека.
Так как указатель вершины не изменит своего значения.
В этом примере ты не управляешь указателем вершины стека.

Ты просто берешь адрес из одного указателя и записываешь его в другой.

C++
1
2
3
4
5
6
void push(Node *top,int d){
Node *p = new Node;
p->d=d;
p->next=top;
top=p;       
}
Вот теперь попробуй сделать так, если ты не понял:

C++
1
2
3
4
5
6
7
8
//От этой функции толку не будет память будет выделена в локальный указатель.
void my_new(int *p){
p = new int;           //бестолковая утечка памяти, даже эту память клиент использовать не может.
}
//Пример её использования.
int *pa;
my_new(pa);
*pa=10;      //ошибка времени. памяти то нет

Вот правильная вариация:
C++
1
2
3
4
5
6
7
8
void my_new(int **p){
*p = new int;         
}
//Пример её использования.
int *pa;
my_new(&pa);
*pa=10;        //обращаемся к выделенной памяти.
delete pa;     //можно и освободить.
Автор зайди сюда, там интересное,
Бесконечность и далее...

после увиденного просьба не задавать вопросы.

Добавлено через 10 минут
Указатель на указатель - разница способов
Тема странно как то называется...

Добавлено через 15 минут
Nameless One:
Дам тебе один совет, который дал мне один мой друг:
Прежде чем что то говорить нужно быть уверенным что это истина,
если ты не уверен посмотри в литературу.
Это я говорю к тому что бы ты не вводил в заблуждения людей,
которые только познают программирование.

Надеюсь ты извлечешь пользу из этого высказывания.
3
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
16.03.2010, 05:33 17
Цитата Сообщение от Krist_ALL
ав каких случаях первый способ рационален а когда второй.
в каких ситуациях?
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    int a = 5;
 
    int *p;
    int **pp;
 
    /* переменная-указатель p может хранить адрес переменной a */
    /* переменная-указатель pp может хранить адрес переменной p */
 
    /* переменная-указатель p не может хранить адрес переменной pp */
    /* переменная-указатель pp не может хранить адрес переменной a */
 
 
    int *ptrarr[5];
    int i;
 
    p = &a;
 
    for (i = 0; i < 5; i++)
        ptrarr[i] = p;
 
    pp = ptrarr;
 
    /* мы можем перемещать указатель pp по массиву указателей ptrarr */
 
    for (i = 0; i < 5; i++) {
        printf("%d" "\n", **pp);
        pp++;
    }
argv устроен именно так
1
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
16.03.2010, 06:00 18
Цитата Сообщение от Krist_ALL Посмотреть сообщение
int *f = b; //Втрой способ
. Копия указателя, а не указатель на указатель. То есть это ещё один указатель на а.

Добавлено через 1 минуту
Цитата Сообщение от Nameless One Посмотреть сообщение
его не адресом указателя b, а значением
. Вот именно. Так куда указатель?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
16.03.2010, 09:59 19
Genius Ignat, Спасибо, я понял свою ошибку
2
16.03.2010, 09:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.03.2010, 09:59
Помогаю со студенческими работами здесь

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

Функция, получающая указатель на обычную функцию, получает указатель на метод класса
Здравтсвуйте. Имеется вопрос по указателям на методы класса. Допустим, есть функция( f ), которая...

Функция, принимающая указатель и число байт и выделяющая память под указатель
Здравствуйте. Задача легкая, но почему-то завис Нужно написать функцию, принимающую указатель и...

Указатель на функцию, которая принимает в качестве параметра указатель на массив
я не понимаю. вроде делаю правильно, но выходит ошибка. есть функция. int foo(int *mas){};...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru