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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> возвращаем указатель 
:(
    Опции темы
GQU
Дата 13.8.2014, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



почему нельзя возвращать указатель, а локальную переменную можно?
PM MAIL   Вверх
Cheloveck
Дата 13.8.2014, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

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



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


--------------------
user posted image
PM Jabber   Вверх
EnergoHokum
Дата 13.8.2014, 06:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Ровно наоборот. Если в функции была выделена память (операторами new или new[]), и возвращён указатель на неё, то после завершения функции эта память "останется в живых", и скопировав возвращённый указатель, можно добраться до неё. Разумеется, выделенное надо будет потом где-нить освободить. А если попытаться возвратить временную переменную, созданную на стеке функции, то после возврата из этой функции стек будет уничтожен, и что там окажется в этой переменной -- никто не знает. Может, корректные данные, а может быть и мусор.
PM MAIL ICQ   Вверх
math64
Дата 13.8.2014, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Нельзя возвращать указатель или ссылку на локальную переменную.
Можно возвращать указатель на выделенную память (операторами new или new[]).
Можно возвращать указатель или ссылку на static переменную.
Можно возвращать указатель или ссылку, переданные в качестве параметра (но не всегда)
Можно возвращать локальную переменную или поле класса. Результат будет скопирован в соответствующую переменную вызывающей функции (при необходимости будет вызван оператор или конструктор копирования).
PM   Вверх
Cheloveck
Дата 13.8.2014, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

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



Цитата(EnergoHokum @  13.8.2014,  07:43 Найти цитируемый пост)
Ровно наоборот

Нет, не наоборот. Когда возвращаешь переменную, то она копируется. Указатель, собственно, тоже копируется, но остаётся указателем на переменную в стеке, которая перетрётся при первой возможности.
Конечно же можно вернуть указатель на нестековую переменную или на данные, переданные в аргументах по указателю или ссылке.


--------------------
user posted image
PM Jabber   Вверх
EnergoHokum
Дата 13.8.2014, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Когда возвращаешь переменную, то она копируется. Указатель... остаётся указателем на переменную в стеке

В общем, всё, что лежит на стеке функции -- не возвращать (через указатель ли, через ссылку). Копии лежащего на стеке функции возвращать можно, указатели на динамически выделенную в теле функции память возвращать можно.

Теперь осталось рассказать, что такое "стек функции", и как он функционирует.
PM MAIL ICQ   Вверх
math64
Дата 13.8.2014, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



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

PM   Вверх
GQU
Дата 13.8.2014, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Спасибо всем, разобрался вроде
Цитата

 Указатель, собственно, тоже копируется, но остаётся указателем на переменную в стеке, которая перетрётся при первой возможности

попробуй перетри smile 
Код

#include <stdio.h>
#include <stdlib.h>

//laga затирает стек
void laga(){
    int a,b,c,d,e,f,g,h,i,a1,b1,c1,d1,e1,f1,g1,h1,i1;
    a=5,b=6,c=7,d=8,i=9,e=10,g=11,h=12,i=13,f=14,a1=5,b1=6,c1=7,d1=8,i1=9,e1=10,g1=11,h1=12,i1=13,f1=14;
}

//tmp меняет местами
int* tmp(int a, int b){
    int* p;
    int tmp;
    tmp=a;
    a=b;
    b=tmp;
    laga();
    p=&a;
    return p;//специально возвращаю адрес
}

void main(){

    int i,j;
    i=5;j=10;
    printf("i = %d",*tmp(i,j));
    printf("\n");

    system("pause");
}


Это сообщение отредактировал(а) GQU - 13.8.2014, 19:27
PM MAIL   Вверх
Cheloveck
Дата 13.8.2014, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

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



Цитата(GQU @  13.8.2014,  20:15 Найти цитируемый пост)
попробуй перетри


Код

#include <stdio.h>
#include <string.h>

int * stack()
{
    volatile int x = 100;
    return &x;
}

int * stack2()
{
    volatile int x = 200;
    return &x;
}

int main()
{
    int * s = stack();
    printf("%i\n", *s);
    int * s2 = stack2();
    printf("%i\n", *s);
    return 0;
}


http://codepad.org/DudxDuRw


--------------------
user posted image
PM Jabber   Вверх
GQU
Дата 13.8.2014, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



на строке  
Код

 return &x

ошибка
error C2440: return: невозможно преобразовать "volatile int *" в "int *"

Это сообщение отредактировал(а) GQU - 13.8.2014, 20:11
PM MAIL   Вверх
Cheloveck
Дата 13.8.2014, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

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



Цитата(GQU @  13.8.2014,  21:10 Найти цитируемый пост)
ошибка
error C2440: return: невозможно преобразовать "volatile int *" в "int *"

gcc прожевал. Попробуй убрать volatile.


--------------------
user posted image
PM Jabber   Вверх
GQU
Дата 13.8.2014, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

gcc прожевал. Попробуй убрать volatile. 

ну я убрал, все норм, сейчас разбираюсь со стеком, почему в моем случае не перетерает, просто я неправильно представляю пока еще как работает стек
понял, у меня не затирается, потому что переменные создаются, уничтожаются, (при выходе из функции), адрес, на который ссылается локальная переменная остается тот же
просто я думал, что новые переменные перетрут данные, на которые ссылается указатель p, а нет, return-а то еще не было, указатель стека не сместился

Это сообщение отредактировал(а) GQU - 13.8.2014, 21:08
PM MAIL   Вверх
math64
Дата 14.8.2014, 07:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(GQU @  13.8.2014,  20:56 Найти цитируемый пост)
ну я убрал, все норм, сейчас разбираюсь со стеком, почему в моем случае не перетерает

А ты не полагайся на случай - просто так не делай.
Вот так можно:
Код

int * stack()
{
    static int x = 100;
    return &x;
}

Вот так тоже можно:
Код

int* tmp(int& a, int& b){
    int* p;
    int tmp;
    tmp=a;
    a=b;
    b=tmp;
    p=&a;
    return p;//специально возвращаю адрес
}

но результат можно сохранять только пока существуют переменные, указанные  в вызове tmp.

PM   Вверх
EnergoHokum
Дата 14.8.2014, 07:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

почему в моем случае не перетирает

Потому что затирание будет зависеть от погоды на Марсе, фазы Луны, заданных опций оптимизации компилятора, и ещё тонны факторов, которые не учесть. Потому, во избежание, надо считать, что переменные, размещённые на нём, после завершения работы функции "сломаны".
Цитата

просто я неправильно представляю пока еще как работает стек

Если дружишь с english language, то вот. Если не дружишь -- срочно начинай дружить. Хорошей литературы на русском исчезающе мало.
PM MAIL ICQ   Вверх
baldina
Дата 14.8.2014, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(EnergoHokum @  14.8.2014,  07:21 Найти цитируемый пост)
Хорошей литературы на русском исчезающе мало

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

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

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

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

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


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

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


 




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


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

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