我认为我对跳过列表的工作方式有一个基本的了解,但除了作为C-beginner之外,对它们不熟悉让我对几点感到困惑,尤其是列表的初始化。这是我要遵循的代码:
#define MAXSKIPLEVEL 5
typedef struct Node {
int data;
struct Node *next[1];
} Node;
typedef struct SkipList {
Node *header;
int level;
} SkipList;
// Initialize skip list
SkipList* initList() {
SkipList *list = calloc(1, sizeof(SkipList));
if ((list->header = calloc(1, sizeof(Node) + MAXSKIPLEVEL*sizeof(Node*))) == 0) {
printf("Memory Error\n");
exit(1);
}
for (int i = 0; i < MAXSKIPLEVEL; i++)
list->header->next[i] = list->header;
return list;
}
我还没有在C中使用指针数组做任何事情,所以我觉得我对它们的工作原理有点了解。如果有人能够帮助我,我会有一些问题。
首先,我做了sizeof(int)
得到了4,sizeof(Node*)
得到了8,所以我希望sizeof(Node)
等于12,但结果是16,为什么会这样?与SkipList
的大小相比,其内容大小相同。我把typedef
和[1]
拿出来看看是否有原因,但尺寸仍然是16。
第二,为什么struct Node *next[1]
中的[1]?以后list->header->next[i]
需要它吗?可以next[i]
高于1吗?是不是因为每个节点的指针数量都是可变的,所以你把它变成一个数组,然后再单独增加它?
第三,为什么list->header->next[i] = list->header
最初而不是NULL
?
非常感谢任何建议/意见,谢谢。
答案 0 :(得分:1)
由于结构填充,sizeof
数字为16。
许多架构要求或强烈偏好指针在某个边界上对齐(例如,4字节边界,8字节边界等)如果指针“未对齐”,它们将失败,或者它们将缓慢执行。您的C编译器可能在您的结构中间插入4个未使用的字节,以便您的8字节指针在8字节边界上对齐,这会导致结构大小增加4个字节。
C FAQ提供了更多解释。
答案 1 :(得分:1)
对于您的第一个问题 - 为什么不是struct
其成员大小的大小? - 这是由于 struct padding ,其中编译器(通常出于对齐原因)可能会在struct
成员之间或之后添加额外的空格,以便将大小增加到一些基本尺寸的好的倍数(通常是8或16)。没有可移植的方法来强制结构的大小正好与其成员的大小相同,尽管大多数编译器都有一些自定义开关可以翻转来执行此操作。
关于你的第二个问题 - 为什么[1]
? - 这里的想法是,当您实际分配节点struct
之一时,您将对空间进行过度分配,以便struct
末尾的内存可用于指针。通过创建一个长度为1的数组然后分配空间,您可以在语法上方便地访问这个已分配的空间,就像它始终是struct
的一部分一样。较新版本的C有一个名为灵活阵列成员的概念已经取代了这种技术;我建议谷歌搜索它,看看是否有帮助。
对于您的最后一个问题 - 为什么list->header->next[i]
最初指向list->header
而不是NULL
? - 没有看到更多的代码,很难说。链接列表结构的许多实现使用这样的某种技巧来避免在实现中对NULL
的特殊情况,并且完全有可能在这里使用这种技巧。