在 C 语言中分配的结构指针的"default value"



我正在存储包含特定顺序的输入数据,因此我选择使用数组对它们进行排序:

struct Node** array = (struct Node**)malloc(sizeof(Node**) * DEFAULT_SIZE);
int i;
int size = DEFAULT_SIZE;
while(/* reading input */) {
// do something
int index = token;    // token is part of an input line, which specifies the order
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
*node = (struct Node){value, index};
// do something
if (index >= size) {
array = realloc(array, index + 1);
size = index + 1;
}
array[index] = node;
}

我正在尝试遍历数组并在索引中存在节点时执行某些操作

int i;
for (i = 0; i < size; i++) {
if (/* node at array[i] exists */) {
// do something
}
}

如何检查数组的特定索引处是否存在节点?(或者结构节点在我分配内存后的"默认值"是什么?我只知道这不是NULL...

我应该使用calloc并尝试if ((int)array[index] != 0)吗?或者我可以使用更好的数据结构?

当您realloc(或malloc(指针列表时,系统会调整数组的大小/移动数组,根据需要复制数据,并在不更改数据的情况下保留更多空间,因此您可以获得以前的内容。您不能依赖这些值。

只有calloc执行零初始化,但当您realloc时无法calloc

对于初学者,您可能应该使用calloc

struct Node** array = calloc(DEFAULT_SIZE,sizeof(*array));

在循环中,只需使用realloc并将新内存设置为NULL,以便您可以测试空指针

请注意,您的realloc大小不正确,您必须乘以元素的大小。还要在重新分配后更新size,否则不会多次工作。

请注意棘手memset,它仅将未分配的数据清零,而不更改有效的指针数据。 由于指针算法,array+size计算正确的地址大小,但 size 参数以字节为单位,因此您必须乘以sizeof(*array)(元素的大小(

if (index >= size)
{
array = realloc(array, (index + 1)*sizeof(*array));  // fixed size
memset(array+size,0,(index+1-size) * sizeof(*array));  // zero the rest of elements
size = index+1;  // update size
}

旁白:

  • realloc每个元素效率低下,您应该按块重新分配以避免过多的系统调用/副本
  • 我简化了malloc调用,不需要强制转换malloc的返回值,也最好传递sizeof(*array)而不是sizeof(Node **)。如果所涵盖的array类型发生变化(还可以保护您免受带星标类型的一次性错误的影响(

新分配的内存包含垃圾,从未初始化的内存中读取指针是一个错误。

如果您改用calloc( DEFAULT_SIZE, sizeof(Node*) )进行分配,则将定义数组的内容:所有位都将设置为零。 在许多实现中,这是一个NULL指针,尽管标准不能保证这一点。 从技术上讲,如果您尝试读取所有位设置为零的指针,则可能存在符合标准的编译器,该编译器会使程序崩溃。

(不过,只有语言律师需要担心这一点。在实践中,即使是五十年前的大型机,人们也提出了一个机器的例子,其中NULL不是二进制0,更新了它的C编译器,将0识别为NULL指针,因为这破坏了太多的代码。

执行所需操作的安全、可移植方法是将数组中的每个指针初始化为NULL

struct Node** const array = malloc(sizeof(Node**) * DEFAULT_SIZE);
// Check for out-of-memory error if you really want to.
for ( ptrdiff_t i = 0; i < DEFAULT_SIZE; ++i )
array[i] = NULL;

循环执行后,数组中的每个指针都等于NULL!运算符为其返回 1,直到它被设置为其他值。

realloc()调用是错误的。 如果您确实想这样做,则 size 参数应该是新的元素数乘以元素大小。 该代码将愉快地使其成为所需大小的四分之一或八分之一。 即使没有内存损坏错误,您也会发现自己过于频繁地进行重新分配,这可能需要将整个阵列复制到内存中的新位置。

经典的解决方案是创建一个数组页面的链接列表,但是如果您要realloc(),最好每次将数组大小乘以一个常量。

同样,当您创建每个Node时,如果您关心可移植性,则需要初始化其指针字段。 如果你这样做,本世纪没有编译器会生成效率较低的代码。

如果仅按顺序分配节点,则另一种方法是创建Node数组而不是Node*数组,并维护正在使用的节点数的计数器。现代桌面操作系统只会映射进程写入的阵列物理内存页数,因此在大多数环境中,简单地分配而不初始化大型动态数组不会浪费实际资源。

另一个可能是良性的错误:数组的元素具有类型struct Node*,但您为每个元素分配sizeof(Node**)而不是sizeof(Node*)字节。 但是,编译器不会对此进行类型检查,并且我不知道任何编译器这两种对象指针的大小可能不同。

您可能需要这样的东西

unsigned long i;
for (i = 0; i < size; i++) {
if (array[i]->someValidationMember==yourIntValue) {
// do something
}
}

编辑。 要分配的内存必须为空。或者,如果删除了某个项目,只需将 Node 成员更改为零或您选择的任何内容即可。

相关内容

  • 没有找到相关文章

最新更新