如何从单个函数返回不同的类型

时间:2016-05-25 09:50:54

标签: c function return void-pointers

我有以下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的随机值
我想要的是拥有一般功能谁可以返回不同类型的值而不是使用两个函数。那可能吗 ?如果是这样,怎么办?

5 个答案:

答案 0 :(得分:8)

我看到的问题是,您正在尝试return来自函数(范围)的局部变量的地址,并尝试从调用者访问返回的内存。在调用者中,内存无效,任何使用都将导致undefined behavior

解决方案:您需要为函数中的malloc()指针(calloc() / return)使用动态内存分配。这将解决这里的问题,因为动态分配的内存的生命周期直到free() - 手动或直到程序终止,以较早者为准。

话虽如此,这种做法并不好。如果要返回多种类型中的一种,请转到包含所有类型成员的struct,并使用标记来标记类型。填写相应的成员变量,设置标志和return结构变量。

为了更好,您实际上可以使用union作为结构的成员,因为您一次只需要一种类型。有关正常工作的代码,请参阅{{3>} @pmg

答案 1 :(得分:3)

您可以返回(包含一个结构)联合

#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;
        }
    }
}

请参阅code running at ideone

答案 2 :(得分:1)

您的问题是您要返回本地范围变量的地址。您必须使用动态分配来执行您想要执行的操作。

RewriteRule ^product/(.*)$ products.php?prodName=$1 [L]

答案 3 :(得分:0)

这是因为返回指针的值是本地范围。这意味着当函数返回时,a_chara_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; 
}

在这种特定情况下,您也可以只返回字符串(这将是线程安全的):

#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; 
}

答案 4 :(得分:-1)

如果你想要一个返回两个(或更多)值的函数,你有两种可能:

1-创建函数void并通过引用&amp;

将值作为参数返回

2-声明一个对值进行分组的结构(或类),并使该函数返回此结构的值。