обратный адрес в C - PullRequest
       1

обратный адрес в C

1 голос
/ 14 сентября 2011

Почему этот код дает неожиданный вывод.

int * func(int *xp)
{
    int y = 10 + *xp;
    return (&y);
}
void main()
{
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
}

ожидаемый вывод:

10
20

Реальный вывод:

10
1074194112

Ответы [ 6 ]

11 голосов
/ 14 сентября 2011

Вы возвращаете указатель на переменную (y), которая выходит из области действия в тот момент, когда вы покидаете func.Это неопределенное поведение.

Не совсем ясно, чего вы пытаетесь достичь, но есть несколько способов исправить это:

  1. вернуть значение int по значению;
  2. изменить *xp на месте и ничего не возвращать;
  3. взять дополнительный параметр int* и сохранить там результат (снова возвращая void);
  4. выделить память в куче, используя malloc или new и вернуть ее (вызывающий будет отвечать за правильное освобождение этой памяти).

Невозможно сказать, какие из перечисленныхприменимо к вашей проблеме, не зная более широкого контекста.

И наконец, main() должен вернуть int (спасибо @pmg за то, что вы обнаружили это).Это не связано с проблемой, с которой вы столкнулись, но заслуживает внимания.

2 голосов
/ 14 сентября 2011

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

</ real_life_example>

2 голосов
/ 14 сентября 2011

Потому что у выходит из области видимости, когда функция возвращается. Помните, у был объявлен в стеке. Это неопределенное поведение.

1 голос
/ 14 сентября 2011

func должно выглядеть так:

// C++
int* func(int* xp)
{
    int* y = new int;
    *y = 10 + *xp;
    return y;
}
1 голос
/ 14 сентября 2011

Возвращение адреса локальной переменной и последующее разыменование приводит к неопределенному поведению .

Поскольку вызовы printf используют ту же область памяти (стека), которую использует func, они перезаписывают кадр стека func своими собственными внутренними переменными и аргументами функций.

Чтобы решить эту проблему, выделите память в куче с помощью malloc:

int* func (int *xp) {
  int* res = malloc(sizeof(int));
  if (!res) {
    perror('Cannot allocate memory in func');
    exit(1);
  }
  *res = 10 + *xp;
  return res;
}

Не забудьте free это:

int main(void) {
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
    free(xp);
    return 0;
}
0 голосов
/ 14 сентября 2011

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

int * func(int *xp)
{
    static int y;
    y = 10 + *xp;
    return (&y);
}
void main()
{
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
}

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

...