【问题标题】:Array of pointers confusion with skip list指针数组与跳过列表混淆
【发布时间】:2016-07-19 21:31:04
【问题描述】:

我想我对跳过列表的工作原理有一个基本的了解,但是除了作为 C 初学者之外,对它们来说是新手让我在一些方面感到困惑,尤其是列表的初始化。这是我要遵循的代码:

#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-&gt;header-&gt;next[i] 吗? next[i] 会高于 1 可以吗?是不是因为每个节点的指针数量是可变的,所以你把它变成一个数组,然后再单独增加它?

第三,为什么最初是list-&gt;header-&gt;next[i] = list-&gt;header而不是NULL

非常感谢任何建议/cmets,谢谢。

【问题讨论】:

  • SkipList *list = calloc(1, sizeof(SkipList)); - 你忘了检查这个是否失败。

标签: c arrays pointers skip-lists


【解决方案1】:

对于您的第一个问题 - 为什么struct 的大小不是其成员的大小? - 这是由于struct padding,编译器通常出于对齐原因,可能会在struct 的成员之间或之后添加额外的空格,以使大小达到一个不错的倍数一些基本尺寸(通常为 8 或 16)。没有可移植的方法来强制结构的大小与其成员的大小完全相同,尽管大多数编译器都有一些自定义开关,您可以翻转来执行此操作。

对于您的第二个问题 - 为什么是 [1]? - 这里的想法是,当您实际分配节点structs 之一时,您将过度分配空间,以便struct 末尾的内存可用于指针。通过创建一个长度为 1 的数组然后过度分配空间,您可以在语法上方便地访问这个过度分配的空间,就好像它一直是 struct 的一部分一样。较新版本的 C 有一个称为灵活数组成员的概念,它取代了这种技术。我建议您在谷歌上搜索一下,看看是否有帮助。

对于您的最后一个问题 - 为什么 list-&gt;header-&gt;next[i] 最初指向 list-&gt;header 而不是 NULL? - 没有看到更多的代码很难说。许多链表结构的实现都使用了这样的技巧来避免在实现中对NULL 进行特殊处理,而且这种技巧也完全有可能在这里被使用。

【讨论】:

  • 如果您不介意,我还有一个问题。我在代码中将 mallocs 更改为 calloc,这样我就可以取出一些 0 和 NULL 初始化行,这是出于任何原因的不好做法还是可以这样做?
  • 这很好 - 这是人们使用 calloc 的主要原因之一。用注释记录它并没有什么坏处,这样阅读代码的人就可以更轻松地维护它。
【解决方案2】:

sizeof 数字是 16,因为 结构填充

许多架构要求强烈希望它们的指针在某个边界上对齐(例如,4 字节边界、8 字节边界等)。如果指针“未对齐”,它们要么失败,要么执行缓慢。您的 C 编译器可能会在结构中间插入 4 个未使用的字节,以便您的 8 字节指针在 8 字节边界上对齐,这会导致结构大小增加 4 个字节。

C FAQ 提供了更多解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    相关资源
    最近更新 更多