【问题标题】:How a structure assign itself?结构如何分配自己?
【发布时间】:2021-12-27 19:04:09
【问题描述】:
`#include <stdio.h>
struct uu
{  int x;
  struct uu *p;
};
struct uu fun(struct uu d)
{
  d.x *= 3;  d.p = NULL;
  return d;
} 


main()
{
  struct uu a[3] = {{5,a+2}, {8, a+1}, {11,a}};
  int j;
  for(j=0; j<3; j++) printf("%d  ", a[j].p->x);
  printf("\n");

  a[0].p--;
  a[1].p++;
  a[2].p += 2;

  for(j=0; j<3; j++) printf("%d  ", a[j].p->x);
 printf("\n");
 a[1] = fun(a[0]);
 for(j=0; j<3; j++)
 {
   printf("%d  ", a[j].x);
   if(a[j].p == NULL) break;
  }
}`

在这段代码中,这行struct uu a[3] = {{5,a+2}, {8, a+1}, {11,a}};如何将变量分配给自己以及这行如何

      a[0].p--;
      a[1].p++;
      a[2].p += 2;

改变结构的地址。基本上我很困惑。请帮我。谢谢你的回答。

【问题讨论】:

  • "这行 [...] 如何改变结构的地址?" - 它没有。他们所做的只是更改uu::p 数据成员的
  • 添加struct uu的声明。
  • 余没有任何结构。它只会改变p 的值,无论p 是什么,它不会改变数组或数组元素的地址
  • 您是否想知道如何在自身的初始化中引用a?评估初始化列表时,数组的地址可用。
  • 我正在编辑问题。如果你愿意,你可以再看看。很抱歉打扰你我是编码新手,所以我的知识非常低。

标签: c data-structures struct


【解决方案1】:

让我们看一下代码。声明结构应该相当简单。

struct uu
{
    int x;
    struct uu *p;
};

这种类型的元素将包含一个整数和一个指向相同类型的指针。任何对象都只是一块内存,但我们将结构解释为一些内存,它首先保存一个整数,然后可能是一些我们不用于对齐下一个元素的填充,它是一个指针。这可能并不令人困惑。

然后为函数

struct uu fun(struct uu d)
{
    d.x *= 3;
    d.p = NULL;
    return d;
}

请注意,它采用struct uu 类型的值作为输入。它不是一个指针,而是一个值,所以如果你调用函数,函数会得到一个新变量,该变量可以保存struct u,函数参数被复制到这个变量中。

如果我们像这样定义struct uu 值:

struct uu u1;
u1.x = 42;
u1.p = &u1;

结构的x 值为42,结构的p 指针指向结构本身。这是一个任意的初始化,与函数无关,我只需要在里面放一些值来显示函数调用。

现在,致电fun(u1)。这会在函数实例中创建d 变量,它将进入堆栈中的某个位置,我们将u1 中的所有内容复制到d 中。所以d.x = u1.xd.p = u1.p

注意d.p 指向u1 的地址,而不是d 本身。我们复制了指针,所以它仍然具有相同的值。我们没有重新创建 u1 具有的相同结构;我们只是将相同的数据放入新结构中。

还要注意u1d 是不同的变量。它们在记忆中坐在不同的位置,并且没有任何关系。所以,如果我们修改d,我们会改变它内存中的数据,但是我们不会影响u1一位。

当我们从fun 返回时,我们返回一个新的struct uu,这意味着我们将d 中的数据复制到我们在函数调用中分配的任何内容。

例如,如果我们调用了

struct uu u2 = fun(u1);

函数的结果,当我们在函数中完成时,d 变量被复制到结构体u2 中。之后,d 变量被删除;它只在函数运行时存在。

然后我们进入main() 函数。在这里,您应该指定返回值; main() 从技术上讲会给你正确的类型,但这是不好的做法。你可以使用

int main(void)
{
   ...
}

改为。

我们将数组a定义为

struct uu a[3] = {{5, a + 2}, {8, a + 1}, {11, a}};

由于a 是一个由三个struct uu 组成的数组,这意味着我们在连续内存中有三个struct u。第一个位于地址 a+0,第二个位于 a+1,第三个位于 a+2。

在我们为a分配内存之后,它并没有被初始化,所以访问那里的数据是没有意义的,但是不同元素的地址在那里,在刚刚列出的偏移量处.我们可以安全地使用它们。

初始化{{5, a + 2}, {8, a + 1}, {11, a}} 设置数组的值(不查看其中的数据,这是垃圾;我们只查看偏移量以获取结构中p 字段的一些地址)。

然后我们遍历数组,但是我们不查看每个单元格中的值,我们查看p 指针指向的单元格。

    int j;
    for (j = 0; j < 3; j++)
        printf("%d  ", a[j].p->x);
    printf("\n");

所以,当我们查看第一个单元格时,我们会从最后一个单元格中获取值。

当我们查看第二个元素时,我们实际上是在查看它的 x 值,因为它指向自身。

当我们查看最后一个元素时,指针指向数组中的第一个元素,这就是我们看到的x 值。

当你这样做时

    a[0].p--;
    a[1].p++;
    a[2].p += 2;

将第一个元素中的指针向下移动,从a + 2 移动到a + 1,将第二个元素中的指针向上移动,从a + 1 移动到a + 2,然后将指针移动到最后第二个元素,从aa + 2

这意味着当你遍历数组并跟随指针时,你会得到a[1]a[2]a[2]中的值。

您没有更改任何结构的地址;然而,它们中的指针现在指向别处。

【讨论】:

  • 你应该为此投赞成票。
  • 谢谢,这是我的荣幸
  • 先生,非常感谢您的回答。你帮了我很多。再一次,谢谢你。 @ThomasMailund
猜你喜欢
  • 2019-12-30
  • 2015-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2018-06-17
  • 1970-01-01
  • 2011-06-14
相关资源
最近更新 更多