gpt4 book ai didi

c - 带空指针的动态数组

转载 作者:行者123 更新时间:2023-12-01 08:10:19 25 4
gpt4 key购买 nike

所以在 C 中学习指针,我认为作为一个练习,我可以做一些通用数组,当我像这样使用 void** 时,我让它工作了:

struct array{
void **data;
size_t size, capacity;
};

像这样插入元素:

void array_append(array *a, void *element){
if(a->size == a->capacity){
a->capacity += ARRAY_GROW_CONSTANT;
a->data = realloc(a->data, sizeof(void*)*a->capacity);
}
a->data[a->size++] = element;
}

但这并不是很好。数组存储指向元素的指针,因此当元素的范围结束时,它变得无效,并且它也使数组的内容分散在整个内存中。我认为这可以通过分配元素本身来解决

a->data[a->size++] = element;

我会做类似的事情

a->data[a->size] = malloc(inserted_element_size);
memcpy(a->data[a->size], &element, inserted_element_size);
size++;

但我认为当使用普通的 void* 而不是 void** 时我可以获得相同的功能

struct array{
void *start;
size_t element_size, size;
};

并插入像

这样的元素
void array_append(array *a, void *element){
a->size += 1;
a->data = realloc(a->data, (a->size*a->element_size));
memcpy(a->data + (a->size - 1)*a->element_size, &element, a->element_size);
}

但这会导致段错误,我不知道为什么。据我了解(显然我不了解),指针是内存中的地址,因此如果我有一个连续的内存块,我可以在其中存储任何类型的变量并带有偏移量。

编辑:感谢您的解释,它真的很有帮助。

What is a->data initialized to?

我使用了一个函数来初始化数组,a->data 被初始化为 element_size。

the caller will have to cast the resutl into element *

我想我可以使用宏来缩短输入(我认为这是一件坏事?),但我不知道从 void* 的类型转换的性能结构*

Creating a dynamic array of elements directly seems more practical to me.

但这不允许我将数组用作通用数组吗?我想要的是定义一个通用数组,我可以用它来存储任何类型,比如

array *a1 = create_array(sizeof(int)); // array of int
array *a2 = create_array(sizeof(double)); // array of double
etc...

why do you want your data to be stored in a contiguous block?

因为我认为您需要一个连续的内存块才能使用带偏移量的 memcpy。

最佳答案

什么是 a->data 初始化的?为此,在创建(空)数组时应将其设置为 NULL。

此外,您的地址计算不考虑指针算术。 a->data 是一个指针(指向 void *),因此 (a->size - 1)*a->element_size 偏移量将乘以一个指针(指向 void *)。将 a->data 设置为 void * 会导致编译器错误,因为 void 没有大小。

如果你真的想这样做,最好将 a->data 声明为 char *,保证其大小为 1。

注意:访问数组需要强制转换为 (element*)。这将阻止您使用方括号。
您将必须提供访问器功能,例如void * array_at(size_t index) { return &a->data[index*a->element_size]; }
然后调用者必须将结果转换为 element *

直接创建元素的动态数组对我来说似乎更实用。
如果需要,您仍然可以对其调用 realloc

但我想到的第一个问题是:为什么要将数据存储在一个连续的 block 中?

这并不像您想象的那样节省内存,因为重复调用 realloc() 会给内存分配器带来压力,浪费时间进行复制并且可能使堆碎片化甚至超过单个集合mallocs.

关于c - 带空指针的动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20957682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com