URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8115
[ Назад ]

Исходное сообщение
"изменить адреса указателя при вызове функции"

Отправлено flex , 27-Фев-09 04:40 
Здравствуйте!

При вызове функции funcx(int *ptr_xxx) в нее передаю указатель, нужно знать точно при этом действии функция получает именно адрес внешнего указателя и создает еще один, правда локальный указатель внутри себя, или же локальный указатель с тем же адресом не создается, а расширяется область видимости внешнего?

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


Пример:
==============
#include <iostream>
void funcx(int *ptr_xxx) {
    std::cout << "2: " << ptr_xxx << "!\n";
    ptr_xxx = new int;
    std::cout << "3: " << ptr_xxx << "!\n";
}

int main() {
    int* ptr_int;
    std::cout << "1: " << ptr_int << "!\n";
    funcx(ptr_int);
    std::cout << "4: " << ptr_int << "!\n";
    return 0;
}
==============
После выполнения:
1: 0x1! (в мейн)
2: 0x1! (внутри функции получили адресс)
3: 0x804d030! (в нутри функции новый адрес)
4: 0x1! (опять в мейн)

---------
конкретно этот пример можно решить и вернуть указатель через int* funcx(); но как быть если одна функция меняет адреса наподобие примера нескольким указателям funcx(int *ptr_xxx, int *ptr_yyy ). новые адреса для ptr_xxx и ptr_yyy одновременно не вернешь...

Спасибо заранее за пояснения!


Содержание

Сообщения в этом обсуждении
"изменить адреса указателя при вызове функции"
Отправлено jd2 , 27-Фев-09 04:58 
Для этих целей есть указатель на указатель:

int **ptr_ptr_xxx

То есть, в Вашем случае будет что-то вроде:


#include <iostream>
void funcx(int **ptr_ptr_xxx) {
    std::cout << "2: " << *ptr_ptr_xxx << "!\n";
    *ptr_ptr_xxx = new int;
    std::cout << "3: " << *ptr_ptr_xxx << "!\n";
}

int main() {
    int* ptr_int = NULL;
    std::cout << "1: " << ptr_int << "!\n";
    funcx(&ptr_int);
    std::cout << "4: " << ptr_int << "!\n";
    return 0;
}



"изменить адреса указателя при вызове функции"
Отправлено flexik , 27-Фев-09 10:35 
>Для этих целей есть указатель на указатель:
>
>int **ptr_ptr_xxx
>
>То есть, в Вашем случае будет что-то вроде:

Спасибо за ответ и спасибо, что именно с примером. То что нужно. Думал про указатель на указатель, когда специально, прежде чем написать здесь, искал ответ в книге Страуструпа. Видел там указатель на указатель без примера, попробовал, но не получилось использовать. По Вашему примеру все вышло, сейчас попытаюсь найти описание логики работы с ними(что именно делают), чтобы применять не путаясь в программе.


"изменить адреса указателя при вызове функции"
Отправлено Аноним , 27-Фев-09 10:41 

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

Надо было внимательнее читать книги по С (для прокачки скила интуиция :) ), в них во всех ясно говориться что создается копия аргумента и в этом плане указатель ни чем не отличается от просто переменной, т.е. для него точно также создается копия. А значит надо использовать указатель на этот указатель (**ptr). (как бы коммент к посту jd2) :)

PS для C++ есть кроме указателей еще и ссылки, ссылка это просто второе имя для переменной, соответственно можно использовать в данном случае ссылку на указатель в качестве аргумента.


"изменить адреса указателя при вызове функции"
Отправлено flexik , 27-Фев-09 11:05 

>Надо было внимательнее читать книги по С (для прокачки скила интуиция :)
>), в них во всех ясно говориться что создается копия аргумента

Да, про копию знаю, если речь о переменных, в первом своем после про это писал. Просто думал в случае с указателем прозрачно все без копирования. Теперь все ясно.


>PS для C++ есть кроме указателей еще и ссылки, ссылка это просто
>второе имя для переменной, соответственно можно использовать в данном случае ссылку
>на указатель в качестве аргумента.

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

Еще раз всем спасибо за ответы!


"изменить адреса указателя при вызове функции"
Отправлено flexik , 27-Фев-09 12:03 
>PS для C++ есть кроме указателей еще и ссылки, ссылка это просто
>второе имя для переменной, соответственно можно использовать в данном случае ссылку
>на указатель в качестве аргумента.

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


#include <iostream>
void funcx(int &xxx)
{
    std::cout << "2: " << &xxx << "!\n";
    &xxx = new int;
    std::cout << "3: " << &xxx << "!\n";
}

int main()
{
    int* ptr_int;
    std::cout << "1: " << ptr_int << "!\n";
    funcx( *ptr_int );
    std::cout << "4: " << ptr_int << "!\n";
}    

test.cpp: In function `void funcx(int&)':
test.cpp:13(&xxx = new int;): error: ISO C++ forbids cast to non-reference type used as lvalue


"изменить адреса указателя при вызове функции"
Отправлено vic , 27-Фев-09 12:38 
>попробовал, чтобы знать на будущее - вариант со ссылкой не проходит, возможно
>не так что-то делаю, с указателем на указатель работает.


#include <iostream>

void f(int *&p) // ссылка на указатель
{
    p = new int(5); //создаем объект int и возвращаем указатель на него
}

int main()
{
    int *i = NULL;

    std::cout << i << std::endl;
    f(i);
    std::cout << i << " " << *i << std::endl;
    delete i;

    return 0;
}