C将void指针数组传递给函数

C pass void pointer array to function

我想将一个空指针数组传递给一个函数,该函数用结果填充它,它与 integer 一起工作正常,但我无法返回 char*

int function(void *arr[]);
int main(void) {
    void *arr[3];
    function(arr);
    printf("%d\n", *(int *)&arr[0]);
    printf("%d\n", *(int *)&arr[1]);
    printf("%s\n", (char *)&arr[2]);
}
int function(void *arr[]){
    arr[0] = (void*)(int)4;
    arr[1] = (void*)(int)6;
    char* test = "abc";
    arr[2] = (void*)test;
    return 0;
}

对于字符串,我没有得到正确的值

您可以传递 void 的数组,并将该数组元素分配给存储指向值的动态分配内存区域。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int function(void *arr[]){    
    arr[0] = malloc(sizeof(int));
    if (arr[0] == NULL) goto ERR_MALLOC_0;
    *(int*)arr[0] = 4;

    arr[1] = malloc(sizeof(int));
    if (arr[1] == NULL) goto ERR_MALLOC_1;
    *(int*)arr[1] = 6;

    const char *const test = "abc";
    arr[2] = malloc(strlen(test));
    if (arr[2] == NULL) goto ERR_MALLOC_2;
    strcpy(arr[2], test);

    return 0;

    // remember about error checking
    free(arr[2]);
    ERR_MALLOC_2:
    free(arr[1]);
    ERR_MALLOC_1:
    free(arr[0]);
    ERR_MALLOC_0:
    return -1;
}

int main(void) {
    void *arr[3];
    int err = function(arr);
    if (err == -1) abort();

    // & is the address of element, not it's element
    printf("%d\n", *(int*)arr[0]);
    printf("%d\n", *(int*)arr[1]);
    printf("%s\n", (char*)arr[2]);

    // remember to free memory
    for (int i = 0; i < 3; ++i) {
        // funny how we do not need to know the effective type
        free(arr[i]);
    }
}

但是这样的功能显然很混乱,会导致很多很多错误和问题。而只是实际使用适当类型的变量:

#include <stdlib.h>
#include <string.h>

int function(int *val1, int *val2, char **string) {
    *val1 = 3;
    *val2 = 6;
    const char *test = "abc";
    *string = malloc(strlen(test));
    if (*string == NULL) return -1;
    strcpy(*string, test);
    return 0;
}

int main(void) {
    int val1; 
    int val2;
    char *string;
    int err = function(&val1, &val2, &string);
    if (err == -1) abort();

    printf("%d\n", val1);
    printf("%d\n", val2);
    printf("%s\n", string);

    free(string);
}

如果你真的想在不同的数据类型上实现一些虚拟表示和操作,使用普通的“void 指针数组”会让你无处可去,因为这样的数组不知道底层是什么正在存储的值的类型 - 作为程序员,您必须知道该数组中的内容(即 arr[0]intarr[2]char*),所以如您所知,您最好从一开始就使用适当类型的变量。

arr 的类型为 void(*)[3].

arr[0] 的类型为 void*。它存储 4 的适当转换值这一事实是无关紧要的。

&arr[0] 的类型为 void**.

(int *)&arr[0] 具有类型 int*,但它指向类型 void* 的对象而不是指向类型 int 的对象。这不是指针通常做的事情。你可以有这样一个指针,但是只有你可以合法地用它做的事情是将它转换回正确的类型,在这种情况下void**。你没有那样做。

*(int *)&arr[0] 的类型为 int.

此处您通过类型 int 的左值访问类型 void* 的对象。这是未定义的行为。不要那样做。

如果您想将 arr[0] 转换回 int,只需这样做:

printf("%d\n", (int)arr[0]);

同样,如果您想将 arr[2] 转换回 char*,请执行以下操作:

printf("%s\n", (char*)arr[2]);
arr[0] = (void*)(int)4;

上面一行将整数 4 转换为 void 指针(地址)并将其作为指针地址存储在数组 arr 中。我猜这不是你想要的。

为了按照您想要的方式使用 void 指针访问数据,首先使其指向一个有效的内存地址,该地址将在函数退出时保存数据。在将内存地址分配给函数内部的 void 指针时必须小心,当函数退出时,该函数堆栈中的所有变量(局部变量)都将从堆栈中弹出,从而使该内存地址无效。如果要在函数外部使用它,则在将内存地址分配给函数内部的指针时仅使用静态(或全局)或动态内存。