Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
 Аватар для Krist_ALL
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317

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

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

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

и как сделать укзатель на указатель на указатель?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.03.2010, 14:18
Ответы с готовыми решениями:

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

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

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

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

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

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

ВТорой

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

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

Решение

Ты не прав. Это два разных способа, и используются они в разных случаях (конечно же, в твоем случае второй способ не используется, как нерациональный)
Первый способ. Ты объявляешь целую переменную 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
 Аватар для Krist_ALL
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
15.03.2010, 15:23  [ТС]
Это я понимаю)
ав каких случаях первый способ рационален а когда второй.
в каких ситуациях?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
15.03.2010, 15:26
Цитата Сообщение от 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
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 15:27
Evg, ну я же написал - для наглядности
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
15.03.2010, 15:28
Цитата Сообщение от Nameless One Посмотреть сообщение
Evg, ну я же написал - для наглядности
Я понял, но не сразу Удалил
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 15:44
Цитата Сообщение от 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
Двойной указатель используется для передачи простого указателя по адресу.
Могу не большой пример привести: добавление на вершину стека:
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
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 16:06
Genius Ignat, пример, конечно, наглядный, но что нам мешает передавать не адрес указателя, а сам указатель, и не применять лишних операций разыменования?
0
 Аватар для Krist_ALL
10 / 10 / 2
Регистрация: 01.02.2010
Сообщений: 317
15.03.2010, 17:14  [ТС]
а как передавать не адрес указателя, а сам указатель?
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
15.03.2010, 17:18
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
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
15.03.2010, 18:02
Цитата Сообщение от 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
Лучший ответ Сообщение было отмечено как решение

Решение

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
Цитата Сообщение от 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
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
16.03.2010, 06:00
Цитата Сообщение от Krist_ALL Посмотреть сообщение
int *f = b; //Втрой способ
. Копия указателя, а не указатель на указатель. То есть это ещё один указатель на а.

Добавлено через 1 минуту
Цитата Сообщение от Nameless One Посмотреть сообщение
его не адресом указателя b, а значением
. Вот именно. Так куда указатель?
0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
16.03.2010, 09:59
Genius Ignat, Спасибо, я понял свою ошибку
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.03.2010, 09:59
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru