"default value" 在 C 中分配的结构指针
"default value" of allocated struct pointer in C
我正在存储包含特定顺序的输入数据,所以我选择使用数组对它们进行排序:
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
}
}
如何检查数组的特定索引处是否存在节点? (或者分配内存后struct node的"default value"是什么?)我只知道不是NULL
...
我应该使用 calloc
并尝试 if ((int)array[index] != 0)
吗?或者我可以使用更好的数据结构?
您可能需要这样的东西
unsigned long i;
for (i = 0; i < size; i++) {
if (array[i]->someValidationMember==yourIntValue) {
// do something
}
}
编辑。
要分配的内存必须是空白的。或者,如果一个项目被删除,只需将节点成员更改为零或您选择的任何一个。
当你realloc
(或malloc
)你的指针列表时,系统resizes/moves数组,如果需要复制你的数据,并提前预留更多space 无需更改数据,因此您可以获得之前的数据。您不能依赖这些值。
只有 calloc
执行零初始化,但当 realloc
.
时不能 calloc
对于初学者,您可能应该使用 calloc
:
struct Node** array = calloc(DEFAULT_SIZE,sizeof(*array));
在你的循环中,只需使用 realloc
并将新内存设置为 NULL
这样你就可以测试空指针
请注意,您的 realloc
大小不正确,您必须乘以元素的大小。还要在重新分配后更新 size
,否则不会多次工作。
请注意棘手的 memset
,它仅将未分配的数据置零而不更改有效指针数据。由于指针运算,array+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
for each element效率低下,你应该分块重新分配以避免太多系统calls/copies
- 我已经简化了
malloc
调用,不需要转换 malloc
的 return 值,而且最好传递 sizeof(*array)
而不是 sizeof(Node **)
.万一 array
的类型发生变化(也保护您免受带有星号的类型的一次性错误)
新分配的内存包含垃圾,从未初始化的内存中读取指针是一个错误。
如果您使用 calloc( DEFAULT_SIZE, sizeof(Node*) )
分配,则数组的内容将被定义:所有位都将设置为零。在许多实现中,这是一个 NULL
指针,尽管标准并不保证。从技术上讲,如果您尝试读取所有位都设置为零的指针,可能会有一个符合标准的编译器使程序崩溃。
(不过,只有语言律师需要担心这一点。在实践中,即使是 50 岁的大型机,人们也会举出 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
,!
运算符returns 1,直到它被设置为其他东西。
realloc()
调用错误。如果您确实想那样做,则 size 参数应该是新的元素数量乘以元素大小。该代码将愉快地使其成为所需大小的四分之一或八分之一。即使没有内存损坏错误,您也会发现自己过于频繁地进行重新分配,这可能需要将整个数组复制到内存中的新位置。
经典的解决方案是创建数组页面的链接列表,但如果您要realloc()
,最好每次都将数组大小乘以一个常数。
类似地,当你创建每个 Node
时,如果你关心可移植性,你会想要初始化它的指针字段。如果你这样做,本世纪没有编译器会生成效率较低的代码。
如果您只按顺序分配节点,另一种方法是创建一个 Node
而不是 Node*
的数组,并维护一个计数器,记录有多少节点正在使用。现代桌面 OS 只会映射进程写入的数组物理内存页数,因此简单地分配而不初始化大型动态数组不会浪费 most[ 中的实际资源=47=] 环境。
另一个可能是良性的错误:数组元素的类型为 struct Node*
,但您为每个元素分配了 sizeof(Node**)
而不是 sizeof(Node*)
字节。但是,编译器不会对此进行类型检查,而且我不知道任何编译器的这两种对象指针的大小可能不同。
我正在存储包含特定顺序的输入数据,所以我选择使用数组对它们进行排序:
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
}
}
如何检查数组的特定索引处是否存在节点? (或者分配内存后struct node的"default value"是什么?)我只知道不是NULL
...
我应该使用 calloc
并尝试 if ((int)array[index] != 0)
吗?或者我可以使用更好的数据结构?
您可能需要这样的东西
unsigned long i;
for (i = 0; i < size; i++) {
if (array[i]->someValidationMember==yourIntValue) {
// do something
}
}
编辑。 要分配的内存必须是空白的。或者,如果一个项目被删除,只需将节点成员更改为零或您选择的任何一个。
当你realloc
(或malloc
)你的指针列表时,系统resizes/moves数组,如果需要复制你的数据,并提前预留更多space 无需更改数据,因此您可以获得之前的数据。您不能依赖这些值。
只有 calloc
执行零初始化,但当 realloc
.
calloc
对于初学者,您可能应该使用 calloc
:
struct Node** array = calloc(DEFAULT_SIZE,sizeof(*array));
在你的循环中,只需使用 realloc
并将新内存设置为 NULL
这样你就可以测试空指针
请注意,您的 realloc
大小不正确,您必须乘以元素的大小。还要在重新分配后更新 size
,否则不会多次工作。
请注意棘手的 memset
,它仅将未分配的数据置零而不更改有效指针数据。由于指针运算,array+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
for each element效率低下,你应该分块重新分配以避免太多系统calls/copies- 我已经简化了
malloc
调用,不需要转换malloc
的 return 值,而且最好传递sizeof(*array)
而不是sizeof(Node **)
.万一array
的类型发生变化(也保护您免受带有星号的类型的一次性错误)
新分配的内存包含垃圾,从未初始化的内存中读取指针是一个错误。
如果您使用 calloc( DEFAULT_SIZE, sizeof(Node*) )
分配,则数组的内容将被定义:所有位都将设置为零。在许多实现中,这是一个 NULL
指针,尽管标准并不保证。从技术上讲,如果您尝试读取所有位都设置为零的指针,可能会有一个符合标准的编译器使程序崩溃。
(不过,只有语言律师需要担心这一点。在实践中,即使是 50 岁的大型机,人们也会举出 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
,!
运算符returns 1,直到它被设置为其他东西。
realloc()
调用错误。如果您确实想那样做,则 size 参数应该是新的元素数量乘以元素大小。该代码将愉快地使其成为所需大小的四分之一或八分之一。即使没有内存损坏错误,您也会发现自己过于频繁地进行重新分配,这可能需要将整个数组复制到内存中的新位置。
经典的解决方案是创建数组页面的链接列表,但如果您要realloc()
,最好每次都将数组大小乘以一个常数。
类似地,当你创建每个 Node
时,如果你关心可移植性,你会想要初始化它的指针字段。如果你这样做,本世纪没有编译器会生成效率较低的代码。
如果您只按顺序分配节点,另一种方法是创建一个 Node
而不是 Node*
的数组,并维护一个计数器,记录有多少节点正在使用。现代桌面 OS 只会映射进程写入的数组物理内存页数,因此简单地分配而不初始化大型动态数组不会浪费 most[ 中的实际资源=47=] 环境。
另一个可能是良性的错误:数组元素的类型为 struct Node*
,但您为每个元素分配了 sizeof(Node**)
而不是 sizeof(Node*)
字节。但是,编译器不会对此进行类型检查,而且我不知道任何编译器的这两种对象指针的大小可能不同。