-1

我已将我的问题简化为这个小 C 程序。请注意,我正在自学 C。我在指针方面遇到了真正的麻烦!

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

typedef struct Elmt_ {
    int *i;
    struct Elmt_ *next;
} E;

void swap_1(E *x, E *y) {
    int *temp = NULL;
    temp = x->i;
    x->i = y->i;
    y->i = temp;
}

void swap_2(E *x, E *y) {
    int *temp=NULL;
    temp = malloc(sizeof(int));
    *temp = *(x->i);
    *(x->i) = *(y->i);
    *(y->i) = *temp;
}

int main() {
    E *p, *q, *r, *s;

    int a, b;
    a = 8;
    b = 50;

    p = malloc(sizeof(E));
    q = malloc(sizeof(E));
    p->i = &a;
    p->next = NULL;

    q->i = &b;
    q->next = NULL;
    printf("Initially, *(p->i)=%d *(q->i)=%d\n", *(p->i), *(q->i));
    swap_1(p,q);
    printf("After swap_1, *(p->i)=%d *(q->i)=%d\n", *(p->i), *(q->i));

    r = malloc(sizeof(E));
    s = malloc(sizeof(E));
    r->i = &a;
    s->i = &b;
    printf("Initially, *(r->i)=%d *(s->i)=%d\n", *(r->i), *(s->i));
    swap_2(r,s);
    printf("After swap_2, *(r->i)=%d *(s->i)=%d\n", *(r->i), *(s->i));
    return 0;
}

**问题:**在上面的程序中,交换所指向的整数值是swap_1还是正确的方法?swap_2i

我看到这两个函数似乎都正确地交换了作为参数给出的值。

$ ./a.out
Initially, *(p->i)=8 *(q->i)=50
After swap_1, *(p->i)=50 *(q->i)=8

Initially, *(r->i)=8 *(s->i)=50
After swap_2, *(r->i)=50 *(s->i)=8
4

2 回答 2

2

函数swap_1交换指针值,而不是指针值。

函数swap_2交换指向的值,但会产生内存泄漏。

为了干净地交换指向的值,您可以简单地执行以下操作:

void swap_3(E *x, E *y) {
    int temp;
    temp = *(x->i);
    *(x->i) = *(y->i);
    *(y->i) = temp;
}
于 2022-01-06T05:25:23.943 回答
1

让我们来看看这个swap_1功能:

void swap_1(E *x, E *y) {
    int *temp = NULL;
    temp = x->i;
    x->i = y->i;
    y->i = temp;
}

画出每一步,看看会发生什么。

  • 让我们从

    int *temp = NULL;
    

    并查看您拥有的所有指针以及它们指向的位置,然后它看起来像这样:

    +------+
    | temp | --> NULL
    +------+
    
    +---+     +---+     +-------------+
    | x | --> | i | --> | a from main |
    +---+     +---+     +-------------+
    
    +---+     +---+     +-------------+
    | y | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    
  • 现在让我们做第一个任务:

    temp = x->i;
    

    看看它是如何改变事物的:

    +------+
    | temp | ----------\
    +------+           |    +-------------+
                       >--> | a from main |
    +---+     +---+    |    +-------------+
    | x | --> | i | --/
    +---+     +---+ 
    
    +---+     +---+     +-------------+
    | y | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    

    如您所见,您现在有两个指针,都指向同一个位置(a来自main函数的变量)。

  • 现在让我们做第二个作业:

    x->i = y->i;
    

    这将改变这样的事情:

    +------+     +-------------+
    | temp | --> | a from main |
    +------+     +-------------+
    
    +---+     +---+
    | x | --> | i | --\ 
    +---+     +---+   |    +-------------+
                      >--> | b from main |
    +---+     +---+   |    +-------------+
    | y | --> | i | --/
    +---+     +---+
    

    同样,您有两个指针都指向同一个位置(两者x->iy->i指向函数中的变量bmain

  • 最后是最后一个任务:

    y->i = temp;
    

    完成此分配后,指针将如下所示:

    +---+     +---+     +-------------+
    | x | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    
    +------+
    | temp | ----------\
    +------+           |    +-------------+
                       >--> | a from main |
    +---+     +---+    |    +-------------+
    | y | --> | i | --/
    +---+     +---+ 
    

由此可以清楚地看出,该swap_1函数不会从函数中交换和变量的。相反,它交换指针和. 和的值仍然相同。abmain x->iy->iab

要交换 和 的实际值,ab需要取消引用指针并使用普通的非指针类型temp

void swap_1(E *x, E *y)
{
    int temp = *x->i;  // Copy the value from where x->i points
    *x->i = *y->i;     // Copy the value
    *y->i = temp;      // Copy the value again
}

如果您将来遇到指针问题,使用铅笔和纸来绘制和重绘变量以及与上述类似的指针通常有助于可视化实际发生的情况。我建议你自己试试。

于 2022-01-06T08:04:22.060 回答