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

时间:2020-12-30 10:53:42

标签: c void-pointers

我想将一个空指针数组传递给一个函数,该函数填充它的结果与 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;
}

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

3 个答案:

答案 0 :(得分:2)

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

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

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

(int *)&arr[0] 具有类型 int*,但它指向类型为 void* 的对象,而不是指向类型为 int 的对象。这不是指针通常所做的。您可以拥有这样一个指针,但是您可以合法使用它的唯一事情是将其转换回正确的类型,在本例中为 void**。你没有这样做。

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

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

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

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

同样,如果您想将 arr[2] 转换回 char*,只需这样做:

printf("%s\n", (char*)arr[2]);

答案 1 :(得分:1)

您可以传递一个 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* ),如您所知,您不妨从一开始就使用正确类型的变量。

答案 2 :(得分:1)

arr[0] = (void*)(int)4;

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

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