自引用结构

4
自我引用结构的定义如下:
struct node{
    int data1;
    int data2;
    struct node *ptr;
}obj,*temp;

int main()
{
     printf("\n Address of variable data1 in struct is %p",&obj.data1);
     printf("\n Address of variable data2 in struct is %p",&obj.data2);
}

输出结果为:

结构体中变量 data1 的地址是 0xd0c7010
结构体中变量 data2 的地址是 0xd0c7018

这意味着 data1 占用了 8 字节的内存,对吗?

但如果我有以下结构体定义:

struct node{
    int data1;
    int data2;
}obj,*temp;

int main()
{
     printf("\n Address of variable data1 in struct is %p",&obj.data1);
     printf("\n Address of variable data2 in struct is %p",&obj.data2);
}

输出结果为:

结构体中变量 data1 的地址为 0xd0c6010
结构体中变量 data2 的地址为 0xd0c6014

因此,data1 占用的内存空间为 4 字节,就像整数变量一样,对吗?

但是,在第一种情况下,为什么 data1 占用的内存空间增加了呢?

编辑: 对于第一种情况,输出结果为

Address of variable data1 in struct is 0x600940
Address of variable data2 in struct is 0x600944
The address of ptr is 0x600948
The size of struct is 16

对于第二种情况:
 Address of variable data1 in struct is 0x600910
 Address of variable data2 in struct is 0x600914
 The size of struct is 8

我正在Linux上使用gcc (GCC) 4.1.2运行此代码

上述代码可以正常工作,但下面这个呢?

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

struct node
{
  int data;
  struct node *next;
};

// This function prints contents of linked list starting from the given node
void printList(struct node *n)
{
  printf("\n The memory location of n is %p ",n);
  while (n != NULL)
  {
     printf(" %d ", n->data);
     n = n->next;
     printf("\n The memory location of n in while loop is %p ",n);
  }
}

int main()
{
  struct node* head = NULL;
  struct node* second = NULL;
  struct node* third = NULL;

  // allocate 3 nodes in the heap
  head  = (struct node*)malloc(sizeof(struct node));
  second = (struct node*)malloc(sizeof(struct node));
  third  = (struct node*)malloc(sizeof(struct node));

  head->data = 1; //assign data in first node
  head->next = second; // Link first node with the second node
  printf("\n The memory address of head->data is %p ",&head->data);
  printf("\n The memory address of head->next is %p ",&head->next);

  second->data = 2; //assign data to second node
  second->next = third;
  printf("\n The memory address of second->data is %p ",&second->data);
  printf("\n The memory address of second->next is %p ",&second->next);

  third->data = 3; //assign data to third node
  third->next = NULL;

  printf("\n The memory address of third->data is %p ",&third->data);
  printf("\n The memory address of third->next is %p ",&third->next);

  printList(head);

  getchar();
  printf("\n");
  return 0;
}

O/P是指

 The memory address of head->data is 0x215c010
 The memory address of head->next is 0x215c018
 The memory address of second->data is 0x215c030
 The memory address of second->next is 0x215c038
 The memory address of third->data is 0x215c050
 The memory address of third->next is 0x215c058
 The memory location of n is 0x215c010  1
 The memory location of n in while loop is 0x215c030  2
 The memory location of n in while loop is 0x215c050  3
 The memory location of n in while loop is (nil)

为什么现在还有8个字节的差异? 我正在与其他两个相同的环境下运行此代码。


你能说一下你正在使用的系统和编译器版本吗? - CB Bailey
关于您的编辑,对我来说一切看起来都很好。始终有4个字节的填充。 - ckruczek
我也在想同样的问题,但之前有8个字节的差异,我现在再次检查一下。 - user4418808
请看一下我在第一个答案中的最后一条评论。也许编译器做了一些奇怪的事情,将指针移动到了 data1 和 data2 之间的结构体中? - ckruczek
1
不行,因为8字节指针在8字节边界上对齐。4字节int,4字节未使用,8字节ptr,总大小16。如果交换两者,则总大小将为12。未对齐的加载/存储可能在各种平台上效率低下或出现故障,因此需要对齐。 - user3125367
显示剩余8条评论
1个回答

1

结构体填充是你观察到的差异的原因。

我认为你正在使用64位系统,指针大小为8字节(在带有指针的结构体中)。因此,编译器将所有三个成员都对齐到8字节对齐。但在后一种情况下,只有两个int,所以它被对齐到4字节。


如果编译器可以在该系统上将int对齐到4字节边界,那么将两个int放入一个8字节块中,指针放在相邻的8字节块中仍然是有意义的,对吧? - CB Bailey
@CharlesBailey 你说的也有道理。但我不确定为什么。或许,OP可以更新结构体中指针成员的地址,两个结构体的 sizeof 和平台细节,这将能够确切地解释发生了什么。 - P.P
我在 ArchLinux 64 位系统上测试了这段代码,第一次尝试的结果有 4 字节的差异。也许,也许编译器将结构体指针放置在 data1 和 data2 之间。因此,也许他还输出了结构体指针的地址,以便我们/他可以查看。 - ckruczek
1
这将是一个非常不寻常的编译器,它在两个4字节int值之间引入了填充。完全与传统不符。从技术上讲没有错,但我从来没有见过像这样的编译器失误。结构填充可能是原因之一,但如果是这样的话,那意味着该编译器早就应该升级了。而且坦率地说,我不认为GCC 4.1.2中会有那么大的错误。 - Jonathan Leffler
@user3125367 查尔斯·贝利所评论的是更有可能的解释,但是 OP 是如何看到那些地址的呢?而且 OP 更新了帖子并提供了我所要求的信息。由此可以清楚地看出,对于这两种情况,都只有4字节对齐。 - P.P
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接