我写了以下代码:
typedef struct List {
struct List* next;
void *value;
} List;
void freeList(List* list, void destroyElement(void*)) {
while(list != NULL) {
destroyElement(list->value);
struct List* n = list;
list = list->next;
free(n);
}
}
struct List* arr2list(void** array, int length, void* cpyElement(void*), void (*destroyElement)(void*)) {
struct List* head = NULL;
struct List** tail = &head;
for(int i = 0; i < length; i++) {
*tail = calloc(1, sizeof(struct List));
printf("array[%d] = %dn",i,*(((int*)array)+i));
if (*tail == NULL) {
freeList(head, destroyElement);
return NULL;
}
tail[0]->value = cpyElement(array[i]);
tail = &(tail[0]->next);
}
*tail = NULL;
return head;
}
void printList(List* list, void echoElement(void*)) {
while (list != NULL) {
echoElement(list->value);
list = list->next;
}
}
void destroyElement(void* el) {
if (el != NULL) {
struct List* node = el;
node->next = NULL;
free(node);
}
}
void* cpyElement(void* el) {
int *p = malloc(sizeof(*p));
*p = *(int *) el;
return p;
}
void echoElement(void* el) {
if (el != NULL) {
printf("%d ", *(int *) el);
}
}
int main(int argc, char** argv) {
int array_length = argc - 1;
int* array = (int*) malloc(sizeof(*array) * array_length);
for (int i = 0; i < array_length; i++){
*(array + i) = atoi(argv[i + 1]);
}
struct List* root = arr2list((void*) array,array_length,cpyElement, destroyElement);
printList(root,echoElement);
freeList(root,destroyElement);
free(array);
return 0;
}
问题出在tail[0]->value = cpyElement(array[i]);
.我收到这部分的分段错误错误。如果我写它cpyElement(((int*)array)+i);
它可以工作,但我希望函数arr2list
是通用的,更不用说int
了。我该如何解决?我想我知道不可能将void*
转换为int*
,因为它不知道使用哪种尺寸,所以是否有可能听到一些关于如何处理这个问题的建议,以便它起作用?也许改变array
论点?
你需要创建一个指向int
s 的指针数组,然后传递它。是的,这是很多malloc
调用,但这是必要的(因为您正在使用void *
)。
int main(int argc, char** argv) {
struct List *root;
int i, array_length = argc - 1;
int** array = malloc(sizeof(*array) * array_length);
for (i = 0; i < array_length; i++){
array[i] = malloc(sizeof(*array[i]));
*array[i] = atoi(argv[i + 1]);
}
root = arr2list((void **)array,array_length,cpyElement, destroyElement);
printList(root,echoElement);
freeList(root,destroyElement);
free(array);
return 0;
}
此代码:
void destroyElement(void* el) {
if (el != NULL) {
struct List* node = el;
node->next = NULL;
free(node);
}
}
然后需要更改为(实际上,由于特定于平台的错误,它以前只有效):
void destroyElement(void* el) {
free(el);
}
另外,不要投射malloc
的结果。这意味着没有(int *)malloc(...)
.只需使用malloc(...)
,它更安全,不会掩盖错误。
void *
的问题在于,虽然你可以自由地将其他指针类型转换为void *
并再次返回并返回原始指针,但你需要直接这样做 - 你不能传递一个void **
它指向void *
以外的任何东西并期望它工作。
更糟糕的是,在您的情况下,您正在传递一个int
数组,其中需要一系列void *
。 你可以通过将 youtint
s 强制转换为intptr_t
然后void *
存储在你的列表中来处理这个问题——你必须再次执行双重投射才能再次将它们取出:
void echoElement(void* el) {
printf("%d ", (int)(intptr_t)el);
}
int main(int argc, char** argv) {
int array_length = argc - 1;
void *array = malloc(sizeof(*array) * array_length);
for (int i = 0; i < array_length; i++) {
array[i] = (void *)(intptr_t)atoi(argv[i + 1]);
}
struct List* root = arr2list((void*) array,array_length,cpyElement, destroyElement);
printList(root,echoElement);