我正在尝试创建一个结构元素数组,并在需要新元素时重新分配。该数组必须是一个指针,因为我想从该函数返回它。
我有以下代码:
#include <stdio.h>
#include <stdlib.h>
struct rle_element {
int length;
char character;
};
void get_rle() {
struct rle_element *rle = malloc(sizeof(struct rle_element*));
struct rle_element **rle_pointer = &rle;
rle = realloc(rle, sizeof(rle) + sizeof(struct rle_element*));
(*rle_pointer)->length = 10;
printf("%d\n", (*rle_pointer)->length);
rle_pointer = &rle+1;
(*rle_pointer)->length = 20;
printf("%d\n", (*rle_pointer)->length);
}
int main() {
get_rle();
return EXIT_SUCCESS;
}
但是此代码实际上并不起作用。 我认为重新分配是不正确的。
现在,我有下面的代码可以正常工作。 但是我也可以不分配而使用rle [2]或rle [3]。我认为我的程序只能为两个项目分配空间。
#include <stdio.h>
#include <stdlib.h>
struct rle_element {
int length;
char character;
};
void get_rle() {
struct rle_element *rle = malloc(sizeof(struct rle_element));
struct rle_element **rle_pointer = &rle;
rle = realloc(rle, sizeof(rle) + sizeof(struct rle_element));
rle[0].length = 10;
printf("%d\n", rle[0].length);
rle[1].length = 20;
printf("%d\n", rle[1].length);
}
int main() {
get_rle();
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
您的代码存在各种问题(在注释和其他答案中指出)。您缺少的一件事是您没有跟踪分配区域的大小。 sizeof()
在编译时进行评估(除非您使用的是C99 VLA)。因此,sizeof(rle)
不会求出数组正在使用的字节数。您必须单独存储。这是一个有效的实现,它使用struct rle_parent
结构跟踪大小,并附带注释以帮助您理解:
#include <stdio.h>
#include <stdlib.h>
struct rle_element {
int length;
char character;
};
struct rle_parent {
struct rle_element *arr;
size_t count;
};
static void get_rle(struct rle_parent *p, int length, char character) {
struct rle_element *e;
/* Allocate enough space for the current number of elements plus 1 */
e = realloc(p->arr, (p->count + 1) * sizeof(struct rle_element));
if (!e) {
/* TODO: (Re)allocation failed, we should handle this */
return;
}
/* Update the parent to point to the reallocated array */
p->arr = e;
/* Update our newly added element */
e = &p->arr[p->count];
e->length = length;
e->character = character;
/* Bump the count so we know how many we have */
p->count++;
}
int main() {
struct rle_parent p;
size_t i;
/* Initialize */
p.arr = NULL;
p.count = 0;
get_rle(&p, 10, 'a');
get_rle(&p, 20, 'b');
get_rle(&p, 30, 'c');
/* Print out our array */
for (i = 0; i < p.count; i++) {
struct rle_element *e = &p.arr[i];
printf("%d -- %c\n", e->length, e->character);
}
return 0;
}
或者,如果您不想保持计数,则可以向struct rle_element
添加另一个字段,以指示它是数组中的最后一个元素。每次添加一个新元素(在“当前”最后一个元素上清除它并在“新”最后一个元素上设置它)时,您都必须进行更新,但是在这种情况下,您可以摆脱struct rle_parent
此外,将NULL
作为realloc()
的第一个参数传递,使其表现得像对malloc()
的调用,因此在这里可以正常工作。
答案 1 :(得分:0)
虽然已经提到您是在分配指针的空间而不是结构本身,但是还有另一个问题。
rle_pointer = &rle+1;
not 不会为您提供指向rle [1]的指针的地址。
在提出其他更改的情况下,您仍然会遇到段错误,但是如果您还尝试的话
rle[1].length=20;
printf("%d\n", rle[1].length);
代替
(*rle_pointer)->length = 20;
printf("%d\n", (*rle_pointer)->length);
您将使代码成功运行。这表明您的realloc()已成功工作。
为更好地解释,双指针实际上是指向指针的指针。在&rle + 1处没有指针。您的代码正在尝试取消引用不存在的指针。
代替
rle_pointer = &rle+1;
你可以说
rle += 1;
如果您以这种方式坚持。否则,我建议坚持使用rle作为数组,并避免使用双指针。
对于更新:它正在读写未分配的内存(导致UB)afaik。
您可以通过释放rle并尝试执行相同的行为来验证这一点,在gcc 7.4.0上,我可以执行相同的操作。
答案 2 :(得分:0)
malloc和realloc需要在内存中保留(分配)的空间大小,因此,如果要创建一个数组,必须分配1个元素的大小乘以数组中元素的数量,我建议您制作一个变量来保存数组的大小。 据我所知,顺便说一句“分段错误”表示您正在使用未分配的空间。