如何从单个函数返回不同的类型
我有以下c代码:
#include #include 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
的指针( malloc()
/ calloc()
)使用动态内存分配。 这将解决这里的问题,因为动态分配的内存的生命周期是直接free()
d手动或直到程序终止,以较早者为准。
话虽如此,这种方法并不好。 如果您想要返回多种类型中的一种,请转到包含所有类型成员的struct
,并使用标记来标记该类型。 填充相应的成员变量,设置标志并return
结构变量。
为了更好,您实际上可以使用union
作为结构的成员,因为您一次只需要一种类型 。 有关工作代码,请参阅@pmg 的其他答案 。
您可以返回(包含结构)联合
#include #include #include #include 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) { rxintp = malloc(sizeof (int)); // remember to free(intp) at some time *rxintp = 42; r.lastunionmember = 1; } if (choice == 1) { rxcharp = malloc(42); // remember to free(charp) at some time strcpy(rxcharp, "forty two"); r.lastunionmember = 2; } if (choice == 2) { rxdoublev = 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", *xxintp); break; case 2: printf("string is \"%s\"\n", xxcharp); break; case 3: printf("double value is %f\n", xxdoublev); break; } } }
查看在ideone上运行的代码 。
您的问题是您要返回本地范围变量的地址。 您必须使用动态分配来执行您想要执行的操作。
#include #include 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; }
这是因为返回指针的值是本地范围的 。 这意味着当函数返回时, a_char
和a_int
变量实际上不再存在,因此对它们的引用(指针)无效。
您看到随机输出的原因是因为这些变量使用的内存现在被其他东西使用。
您可以在更宽的范围(即文件范围或程序范围)声明这些变量,也可以使用动态内存分配。
此示例使用文件范围变量:
#include #include 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; }
在这种特定情况下,您也可以只返回字符串(这将是线程安全的):
#include #include 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; }
如果你想要一个返回两个(或更多)值的函数,你有两种可能:
1-使函数为void
并通过引用返回值作为参数&
2-声明一个结构(或类),它对值进行分组并使函数返回此结构的值。