C Void指针的动态数组
我试图创建一个基于动态数组的动态集合抽象数据类型。但是,当我尝试将数据添加到数组时,会收到编译器警告和错误,它们是: 警告:取消引用“void*”指针[默认情况下已启用] 错误:无效使用void表达式 我的代码如下,我用注释标记了有问题的行C Void指针的动态数组,c,arrays,pointers,void-pointers,C,Arrays,Pointers,Void Pointers,我试图创建一个基于动态数组的动态集合抽象数据类型。但是,当我尝试将数据添加到数组时,会收到编译器警告和错误,它们是: 警告:取消引用“void*”指针[默认情况下已启用] 错误:无效使用void表达式 我的代码如下,我用注释标记了有问题的行 struct SET { //general dynamic array void *data; int elements; //number of elements int allocated; // size of array }; struct S
struct SET
{
//general dynamic array
void *data;
int elements; //number of elements
int allocated; // size of array
};
struct SET create()
{
//create a new empty set
struct SET s;
s.data = NULL;
s.elements = 0;
s.allocated = 0; //allocations will be made when items are added to the set
puts("Set created\n");
return s;
}
struct SET add(struct SET s, void *item)
{
//add item to set s
if(is_element_of(item, s) == 0) //only do this if element is not in set
{
if(s.elements == s.allocated) //check whether the array needs to be expanded
{
s.allocated = 1 + (s.allocated * 2); //if out of space, double allocations
void *temp = realloc(s.data, (s.allocated * sizeof(s))); //reallocate memory according to size of the set
if(!temp) //if temp is null
{
fprintf(stderr, "ERROR: Couldn't realloc memory!\n");
return s;
}
s.data = temp;
}
s.data[s.elements] = item; //the error is here
s.elements = s.elements + 1;
puts("Item added to set\n");
return s;
}
else
{
fprintf(stdout, "Element is already in set, not added\n");
return s;
}
}
我已经做过关于虚空指针的研究,但很明显我遗漏了一些东西。如果能得到任何帮助,我将不胜感激。感谢阅读,并希望回答 在取消引用之前,需要强制转换
void*
指针
((某些类型*)(s.data))[s.elements]=*(某些类型*)项代码>您试图将数据用作数组,但已将其声明为void*。编译器无法确定是否要将数据类型存储到此数组中
如果您知道要在“数据”中存储什么类型的数据,您可能应该为它声明一个类型。(如char*data或int*data)首先,我认为您希望在结构中包含一个通用指针数组(数组ofvoid*
),因为您的项是void*
,并且您希望将它们存储为一个数组。也就是说,您需要一个动态数组void*
,因此,您应该使用void**
:
struct SET {
void **data;
int elements;
int allocated;
};
当然,您的add
功能需要更新:
struct SET add(struct SET s, void *item) {
if (is_element_of(item, s) == 0) {
if (s.elements == s.allocated) {
s.allocated = 1 + (s.allocated * 2);
void **temp = realloc(s.data, (s.allocated * sizeof(*s.data)));
if (!temp) {
fprintf(stderr, "ERROR: Couldn't realloc memory!\n");
return s;
}
s.data = temp;
}
s.data[s.elements] = item;
s.elements = s.elements + 1;
puts("Item added to set\n");
return s;
}
else {
fprintf(stdout, "Element is already in set, not added\n");
return s;
}
}
注意,realloc
行已更改:您不希望realloc到s.allocated*sizeof(s)
,您希望s.allocated*sizeof(*s.data)
,因为您将存储类型为void*
(*s.data
的类型是void*
,我没有明确地编写void*
,以便更容易适应未来可能的更改)
另外,我认为您应该更改函数以接收和返回指向struct SET
的指针,否则,您将始终围绕结构进行复制(请记住,值是通过copy传递的).我一直在为同一个问题苦苦挣扎。我已经将困惑与我们被教导的void**ptr
是一个二维数组的想法隔离开来。也许它也是一个二维数组,但在大多数情况下,我们想要使用单个指针数组和二维数组的语法只是混淆了这个问题。使用int例如:
int a;
a
是一个变量的名称,该变量引用一个包含int的内存块
int* aPtr;
aPtr
是一个变量的名称,它引用了一个内存块,该内存块拥有size\t
类型。所有指针都是size\t类型,就像所有int都是int类型一样,float都是float类型。它所拥有的size\t将被分配一个地址(aPtr=&a
,或aPtr=malloc(sizeof(int))
)。因为这是一个int指针,分配的地址将是int的大小,它将存储int。因此,您将地址分配给aPtr
。您将值分配给此地址,内存块aPtr
通过取消引用*aPtr=10指向;
读取通过取消引用intv指向的int中的值al=*aPtr;
int** pPtr;
pPtr是一个变量的名称,该变量引用一个包含大小\u t的内存块。此大小\u t中存储的地址是另一个大小\u t内存块的地址,即指针。第二个大小\u t块是包含整数地址的指针。因此,您有:
int a = 10;
int* aPtr = &a;
int* bPtr = malloc(sizeof(int));
*bPtr = 20;
int** pPtr = malloc(2 * sizeof(int*));
pPtr[0] = aPtr;
*(pPtr + 1) = bPtr;
printf("a is %d, aPtr address is %d, aPtr points to %d, bPtr points to %d.\n", a, aPtr, *aPtr, *bPtr);
printf("pPtr[0] points to aPtr which points to %d. Which is to say, qwe dereference pPtr to get to aPtr and dereference aPtr to get to its value.\n", *(pPtr)[0]);
printf("Which can be handled with different syntax illustrated by pPtr[1] to give %d\n", *(*(pPtr + 1)) );
pPtr需要取消引用才能访问它所指向的指针。具体来说,我们希望指向的指针是bPtr
,数组中的第二个元素so*(pPtr+1)
。但我们希望bPtr
指向的值,而不是bPtr
,因此我们必须取消引用*(pPtr+1)因此*(*(pPtr+1))
因此,可以包括空指针:
void** vPtr = malloc(2 * sizeof(void*));
*(vPtr + 0) = aPtr;
*(vPtr + 1) = bPtr;
printf("vPtr[1] is %d\n", *((int*)*(vPtr + 1)));
正如一些评论员已经注意到的,void指针必须转换回type。因此,作为void指针存储在数组中的aPtr
和bPtr
需要转换回int指针:(int*)*(vPtr+1)你应该把所有函数定义都放在这里..看来成员数据应该是空的**?我不确定我是否遵循..数组背后的想法是它可以存储任何类型的数据。然后你需要根据存储在其中的数据类型对其进行适当的强制转换。我已将其强制转换为char*,并进行编译,但我有点担心is违背了数组的用途。如果它是这样工作的,那么为什么不从字符串开始定义数组呢?@MattGrima不客气。动态数组背后的想法总是一样的。当你想在动态数组中存储T
类型的元素时,你必须声明一个指向T的指针。在这种情况下,你想存储void*
在动态数组中,因此您需要一个指向void*
的指针,即void**
。如果您遵循此思路,您将永远不会再犯此错误:)但是请记住,当您从集合中弹出这些元素时,如果要取消引用指针,则接收它们的函数必须知道它们的类型。