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]
是 int
而 arr[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 指针时必须小心,当函数退出时,该函数堆栈中的所有变量(局部变量)都将从堆栈中弹出,从而使该内存地址无效。如果要在函数外部使用它,则在将内存地址分配给函数内部的指针时仅使用静态(或全局)或动态内存。
我想将一个空指针数组传递给一个函数,该函数用结果填充它,它与 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]
是 int
而 arr[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 指针时必须小心,当函数退出时,该函数堆栈中的所有变量(局部变量)都将从堆栈中弹出,从而使该内存地址无效。如果要在函数外部使用它,则在将内存地址分配给函数内部的指针时仅使用静态(或全局)或动态内存。