Почему у тебя нет разыменования? - PullRequest
1 голос
/ 01 апреля 2011

Для следующего кода я так понимаю: ссылка на указатель x передается в функцию f, val получает адрес y, который является локальной переменной.Так почему же после выхода из функции f с x все в порядке?у должен был быть разыменован.x равен 5, и оба printf печатают один и тот же адрес.

void f (int ** val)
{
    int y = 5 ;
    *val = & y;
    printf("%d\n", &y);

}

int _tmain(int argc, _TCHAR* argv[])
{

    int * x ;
    f(&x );
    if ( *x == 5 )
        printf("%d", x);
}

Ответы [ 7 ]

7 голосов
/ 01 апреля 2011

Это Неопределенное поведение для доступа к памяти, которой не владеет ваша программа.

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

Может случиться что угодно.

Худшее, что может произойти, - это чтобы программа вела себя так, как вы ожидаете.
Когда это происходит, вы считаете, что делать то, что вы сделали, можно. ЭТО НЕ ОК . Неопределенное поведение - это плохо.

Также не гарантируется, что одно и то же неопределенное поведение происходит и при разных запусках программы. Некоторое время он может работать так, как вы ожидаете, и вылетать, когда вы демонстрируете его клиенту (или своему боссу).

(Некоторые хорошие проявления UB - это сбой, или лимонный сок начинает вытекать из порта USB)

Может случиться что угодно.

3 голосов
/ 01 апреля 2011

x указывает на локальную переменную внутри f, которая больше не действительна к моменту возврата f.

РЕДАКТИРОВАТЬ: Ваше сообщение не дает четкого представления о том, что вы ожидаете, должно произойти, но, как описано гораздо яснее в других ответах, *x указывает на память, которой вы не владеете, а чтение из *x - неопределенное поведение, поэтому все ставки отключены.Если вы пытаетесь прочитать из *x, и оно оказывается равным 5, возможно, это потому, что значение 5 все еще находится в стеке.Попробуйте вставить некоторые вызовы на printf сразу после вызова на f, и вы, вероятно, получите другой результат.

2 голосов
/ 01 апреля 2011

Переменная y находится в стеке. таким образом, вы передаете адрес в стеке x, и это действительный адрес, но с неопределенным содержимым. если вы добавите другую функцию (например, printf) между вызовом f и проверкой *x == 5, вы, вероятно, получите другой результат (поскольку стек был изменен).

1 голос
/ 01 апреля 2011

y живет только в пределах f(int**val), поскольку оно объявлено в этой области.
Ссылка на его адрес вне f() не имеет четкого определения (или, как мы любим досказать: неопределенное поведение.

1 голос
/ 01 апреля 2011

Это классический ...

Переменная y жива только до тех пор, пока выполняется функция f.Как только он возвращается, пространство памяти, занимаемое y в стеке, может использоваться для чего-либо еще.

0 голосов
/ 01 апреля 2011

Как уже почти все сказали, это неопределенное поведение. Причина, по которой вы печатаете правильное значение (5), заключается в том, что ваша программа еще не использовала эту память, пока . Подождите, пока ваша программа поместит что-то еще по этому адресу, тогда вы увидите неправильные результаты.

0 голосов
/ 01 апреля 2011

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

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