如何从单个函数 return 不同类型
How to return different types from a single function
我有以下 C 代码:
#include <stdio.h>
#include <stdlib.h>
void *func(int a) {
if (a==3) {
int a_int = 5;
int *ptr_int = &a_int;
return (void *)ptr_int;
}
else if (a==4) {
char a_char = 'b';
char *ptr_char = &a_char;
return (void *)ptr_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
但是当我使用 gcc 测试这段代码时,我得到以下结果:
int value = 98
char value = �
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value = g
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root@coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value = !
为什么 ptr_int 的 98 和 ptr_char 的 随机值?
我想要的是 一个通用函数 可以 return 不同类型的值而不是使用两个函数。那可能吗 ?如果是这样,该怎么做?
我所看到的问题是,您正试图从函数(作用域)return
获取局部变量的地址,并试图从调用者访问 returned 内存。在调用者中,内存是无效的,任何使用都会导致undefined behavior.
解决方案:您需要为要从函数中 return
的指针 (malloc()
/ calloc()
) 使用动态内存分配。这将解决这里的问题,因为动态分配的内存的生命周期是直到 free()
-d 手动或直到程序终止,以较早者为准。
话虽如此,这种方法并不是一个好的方法。如果您只想 return 多种类型中的一种,请选择包含所有类型成员的 struct
并使用标志来标记类型。填充相应的成员变量,设置标志和return
结构变量。
更好的是,您实际上可以使用 union
作为结构的成员,因为您一次只需要 一种类型。有关工作代码,请参考 @pmg 的 。
这是因为您 return 指针指向的值属于 局部范围 。这意味着当函数 returns 时,a_char
和 a_int
变量实际上不再存在,因此对它们的引用(指针)无效。
您看到随机输出的原因是因为 曾经 被这些变量使用的内存现在被其他东西使用了。
您可以在更广泛的范围(即文件范围或程序范围)声明这些变量或使用动态内存分配。
此示例使用文件范围变量:
#include <stdio.h>
#include <stdlib.h>
static int a_int = 5;
static char a_char = 'b'
void *func(int a) {
if (a==3) {
return (void *)&a_int;
}
else if (a==4) {
return (void *)&a_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
在这种特定情况下,您还可以只 return 个字符串(这将是线程安全的):
#include <stdio.h>
#include <stdlib.h>
char * func(int a) {
if (a == 3) {
return "5";
} else if (a == 4) {
return "b";
} else {
return "Return value is nothing";
}
}
int main (int argc, char *argv[]) {
fprintf(stdout, func(3));
fprintf(stdout, func(4));
fprintf(stdout, func(15));
return 0;
}
您的问题是您返回的是局部范围变量的地址。你必须使用动态分配来做你想做的事。
#include <stdio.h>
#include <stdlib.h>
void *func(int a)
{
void *retVal = NULL;
if (a==3)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((int *)(retVal)) = 5;
}
}
else if (a==4)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((char *)(retVal)) = 'b';
}
}
else
{
fprintf(stderr, "return value is NULL");
}
return retVal;
}
int main ()
{
int *ptr_int = func(3);
char *ptr_char = func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
free(ptr_int);
free(ptr_char);
return 0;
}
如果您想要一个 return 两个(或更多)值的函数,您有两种可能性:
1- 使函数void
和return的值引用为参数&
2- 声明一个对值进行分组的结构(或 class),并使函数 return 成为该结构的值。
您可以return(一个结构包含)联合
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
union members {
int *intp;
char *charp;
double doublev;
};
struct group {
int lastunionmember;
union members x;
};
struct group f1(void) {
struct group r = {0};
int choice = rand() % 3;
if (choice == 0) {
r.x.intp = malloc(sizeof (int)); // remember to free(intp) at some time
*r.x.intp = 42;
r.lastunionmember = 1;
}
if (choice == 1) {
r.x.charp = malloc(42); // remember to free(charp) at some time
strcpy(r.x.charp, "forty two");
r.lastunionmember = 2;
}
if (choice == 2) {
r.x.doublev = 3.14159;
r.lastunionmember = 3;
}
return r;
}
int main(void) {
struct group x;
srand(time(0));
for (int k = 0; k < 20; k++) {
x = f1();
switch (x.lastunionmember) {
default: printf("invalid value\n"); break;
case 1: printf("int value is %d\n", *x.x.intp); break;
case 2: printf("string is \"%s\"\n", x.x.charp); break;
case 3: printf("double value is %f\n", x.x.doublev); break;
}
}
}
我有以下 C 代码:
#include <stdio.h>
#include <stdlib.h>
void *func(int a) {
if (a==3) {
int a_int = 5;
int *ptr_int = &a_int;
return (void *)ptr_int;
}
else if (a==4) {
char a_char = 'b';
char *ptr_char = &a_char;
return (void *)ptr_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
但是当我使用 gcc 测试这段代码时,我得到以下结果:
int value = 98 char value = � root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = g root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = root@coupure:/home/bohao/Desktop/test1375# gcc test.c -o test root@coupure:/home/bohao/Desktop/test1375# ./test int value = 98 char value = !
为什么 ptr_int 的 98 和 ptr_char 的 随机值?
我想要的是 一个通用函数 可以 return 不同类型的值而不是使用两个函数。那可能吗 ?如果是这样,该怎么做?
我所看到的问题是,您正试图从函数(作用域)return
获取局部变量的地址,并试图从调用者访问 returned 内存。在调用者中,内存是无效的,任何使用都会导致undefined behavior.
解决方案:您需要为要从函数中 return
的指针 (malloc()
/ calloc()
) 使用动态内存分配。这将解决这里的问题,因为动态分配的内存的生命周期是直到 free()
-d 手动或直到程序终止,以较早者为准。
话虽如此,这种方法并不是一个好的方法。如果您只想 return 多种类型中的一种,请选择包含所有类型成员的 struct
并使用标志来标记类型。填充相应的成员变量,设置标志和return
结构变量。
更好的是,您实际上可以使用 union
作为结构的成员,因为您一次只需要 一种类型。有关工作代码,请参考 @pmg 的
这是因为您 return 指针指向的值属于 局部范围 。这意味着当函数 returns 时,a_char
和 a_int
变量实际上不再存在,因此对它们的引用(指针)无效。
您看到随机输出的原因是因为 曾经 被这些变量使用的内存现在被其他东西使用了。
您可以在更广泛的范围(即文件范围或程序范围)声明这些变量或使用动态内存分配。
此示例使用文件范围变量:
#include <stdio.h>
#include <stdlib.h>
static int a_int = 5;
static char a_char = 'b'
void *func(int a) {
if (a==3) {
return (void *)&a_int;
}
else if (a==4) {
return (void *)&a_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
在这种特定情况下,您还可以只 return 个字符串(这将是线程安全的):
#include <stdio.h>
#include <stdlib.h>
char * func(int a) {
if (a == 3) {
return "5";
} else if (a == 4) {
return "b";
} else {
return "Return value is nothing";
}
}
int main (int argc, char *argv[]) {
fprintf(stdout, func(3));
fprintf(stdout, func(4));
fprintf(stdout, func(15));
return 0;
}
您的问题是您返回的是局部范围变量的地址。你必须使用动态分配来做你想做的事。
#include <stdio.h>
#include <stdlib.h>
void *func(int a)
{
void *retVal = NULL;
if (a==3)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((int *)(retVal)) = 5;
}
}
else if (a==4)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((char *)(retVal)) = 'b';
}
}
else
{
fprintf(stderr, "return value is NULL");
}
return retVal;
}
int main ()
{
int *ptr_int = func(3);
char *ptr_char = func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
free(ptr_int);
free(ptr_char);
return 0;
}
如果您想要一个 return 两个(或更多)值的函数,您有两种可能性:
1- 使函数void
和return的值引用为参数&
2- 声明一个对值进行分组的结构(或 class),并使函数 return 成为该结构的值。
您可以return(一个结构包含)联合
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
union members {
int *intp;
char *charp;
double doublev;
};
struct group {
int lastunionmember;
union members x;
};
struct group f1(void) {
struct group r = {0};
int choice = rand() % 3;
if (choice == 0) {
r.x.intp = malloc(sizeof (int)); // remember to free(intp) at some time
*r.x.intp = 42;
r.lastunionmember = 1;
}
if (choice == 1) {
r.x.charp = malloc(42); // remember to free(charp) at some time
strcpy(r.x.charp, "forty two");
r.lastunionmember = 2;
}
if (choice == 2) {
r.x.doublev = 3.14159;
r.lastunionmember = 3;
}
return r;
}
int main(void) {
struct group x;
srand(time(0));
for (int k = 0; k < 20; k++) {
x = f1();
switch (x.lastunionmember) {
default: printf("invalid value\n"); break;
case 1: printf("int value is %d\n", *x.x.intp); break;
case 2: printf("string is \"%s\"\n", x.x.charp); break;
case 3: printf("double value is %f\n", x.x.doublev); break;
}
}
}