C указатели - указывают на тот же адрес - PullRequest
4 голосов
/ 28 сентября 2010
#include <stdio.h>
#include <stdlib.h>

void foo(int *a, int *b);

void foo(int *a, int *b) {
    *a = 5;
    *b = 6;
    a = b;
}

int main(void) {
    int a, b;
    foo(&a, &b);
    printf("%d, %d", a, b);
    return 0;
}

Почему a = b (foo) не работает? вывод printf "5, 6" Спасибо.

Ответы [ 7 ]

10 голосов
/ 28 сентября 2010

Это работает; он просто не делает то, что вы думаете.

В foo(), a = b изменяет указатель a так, чтобы он указывал на то, на что b указывает. Это не влияет ни на что, кроме функции; это только меняет указатели.

Если вы хотите изменить значение int, на которое указывает a, таким же, как значение int, на которое указывает b, вам нужно использовать *a = *b, аналогично тому, как назначения в функции уже.

4 голосов
/ 28 сентября 2010

Вызов foo() заканчивается локальными переменными, указывающими на те же адреса, которые хранятся в b .Это изменение не отражено в main(), вызывающем абоненте.

Если вам понравилось сделать это и сделать это изменение постоянным, тогда вам нужно будет передать указатель на указатель на foo() (так что выможет изменить их) вместо их простых значений:

void foo(int **a, int **b) {
    **a = 5;
    **b = 6;
    *a = *b;
}

Я только что заметил, что ваш код несовместим с этой модификацией, так как вы не можете изменить две нормальные переменные, чтобы они указывали друг на друга.Вам также нужно изменить main() таким образом:

int main(void) {
    int a, b;
    int * ptrA = &a;
    int * ptrB = &b;

    foo(&ptrA, &ptrB);
    printf("%d, %d (%d, %d)", *ptrA, *ptrB, a, b);
    return 0;
}
2 голосов
/ 28 сентября 2010

Используя карту псевдопамяти,

В main(),

    a      b
 --------------
|  5   |   6   | <- data
 --------------
 [1000]  [1004]  <- address

В функции foo(),

    a        b      ( local to foo(), different from the a & b in main() )
 ----------------
|  1000  | 1004  | <- data
 ----------------
  [2000]   [2004]  <- address

Итак, когда вОбласть действия foo(),

*a = 5;   // store 5 in int variable a
*b = 6;   // store 6 in int variable b
 a = b;   // copies contents of pointer variable b to a

Итак, окончательная карта в области действия foo():

    a        b
 ----------------
|  1004  | 1004  | <- data
 ----------------
  [2000]   [2004]  <- address
1 голос
/ 28 сентября 2010

В foo, a и b - это отдельные локальные переменные.Установка для них одинакового значения не влияет на предыдущие значения - последняя строка foo в настоящее время в основном ничего не делает.

В пределах foo, a равно изначально указатель на то же местоположение, что и a в main, а b - указатель на то же местоположение, что и b в main.Последняя строка просто делает значение a в foo таким же, как b, а именно указатель на то же место, что и b в main.Поэтому, если вы добавите строку

*a = 7;

в конце foo, вы увидите вывод «5, 7».

(Ваш код определенно будет прощекстати, поговорим о том, использовали ли вы разные имена переменных в main и foo.

Если вы пытаетесь сделать a и b в main "псевдонимом"друг друга, вы не добьетесь успеха.Они являются отдельными локальными переменными в стеке и останутся таковыми.Вы не можете заставить стек «сжаться» под псевдонимом двух, что бы вы ни делали.

0 голосов
/ 28 сентября 2010

a и b являются локальными для функции foo (они находятся в стеке), когда программа возвращается из функции, данные в стеке теряются.когда вы назначаете b для a, вы изменяете только адреса памяти в стеке, а не их значения.

0 голосов
/ 28 сентября 2010

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

0 голосов
/ 28 сентября 2010

Я не уверен, что вы собираетесь после ... если нужно, чтобы a и b содержали одинаковое значение, попробуйте *a = *b.

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