简体   繁体   中英

In C, return 2 variables from a function

Basically, I have a C function that prints out certain numbers and I also want the function to return 2 values. I have tried this out using struct but I did not do this correctly and I am not sure how to proceed. I have read other questions and I understand that using a pointer would be better but I am not sure how to.

My C code is as follows:

struct re_val
{
    double predict_label;
    double prob_estimates;
    predict_label = 5.0;
    prob_estimates = 8.0;
};

int c_func(const char* dir, double a, double b, double c, double d)
{
    double x[] = { a, b, c, d };

    printf("x[0].index: %d \n", 1);
    printf("x[0].value: %f \n", x[0]);

    printf("x[1].index: %d \n", 2);
    printf("x[1].value: %f \n", x[1]);

    printf("x[2].index: %d \n", 3);
    printf("x[2].value: %f \n", x[2]);

    printf("x[3].index: %d \n", 4);
    printf("x[3].value: %f \n", x[3]);

    return re_val;
}

Ultimately, I would like to call only one function that is able to print out the array and return predict_label and prob_estimates .

I am actually calling this function in python via ctypes and my python function is included bellow.

calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
calling_function.c_func.restype =  ctypes.c_double
y = calling_function.c_func("hello",1.1, 2.2, 3.1, 4.2)
print y

First you need to define your structure:

struct re_val{
    float predict_label;
    float prob_estimates;
};

And then you need to return a struct re_val from your function:

struct re_val c_func(const char* dir, float a, float b, float c, float d )
{
    /* ... all that stuff ... */

    struct re_val r;
    r.predict_label = 5.0f;
    r.prob_estimates = 8.0f;   
    return r;
}

So the full example would be:

struct re_val{
    float predict_label;
    float prob_estimates;
};

struct re_val c_func(const char* dir, float a, float b, float c, float d )
{

    /* ... all that stuff ... */

    struct re_val r;
    r.predict_label = 5.0f;
    r.prob_estimates = 8.0f;   
    return r;
}

int main(void)
{
    struct re_val r = c_func("",1.0f,2.0f,3.0f,4.0f);
    printf("predict_label=%.1f\n",r.predict_label);
    printf("predict_label=%.1f\n",r.prob_estimates);
    return 0;
}

Try it here: http://rextester.com/WRROW32352

This is generally done with structures. To initialise it on the stack, do something like this.

#include <stdio.h>  /* printf */
#include <assert.h> /* assert */

struct sample {
    float x[4];
};

struct re_val {
    float predict_label, prob_estimates;
};

/** Returns the re_val of x. */
static struct re_val c_func(const struct sample *const x) {
    struct re_val rv;
    float a;
    assert(x); /* Debug warn if called with null. */
    rv.predict_label = (x->x[0] + x->x[1]) * 5.0f;
    a = x->x[2] + x->x[3];
    if(a < 0.01f) a = 0.01f;
    rv.prob_estimates = 1.0f / a;
    return rv;
}

/** Prints the re_val. */
static void print(const struct re_val *const rv) {
    assert(rv);
    printf("# prediction label\tprobability estimates\n%g\t%g\n",
        rv->predict_label, rv->prob_estimates);
}

int main(void) {
    const struct sample x = { { 0.1f, 0.2f, 1.0f, 100000.0f } };
    const struct re_val rv = c_func(&x);
    print(&rv);
    return 0;
}

See this link Are there any downsides to passing structs by value in C, rather than passing a pointer? ; specifically, the prototype could have been static void c_func(const struct sample *const x, struct re_val *const rv); where rv pointer is filled, especially where re_val is a large structure or one wants it to be potentially allocated on the heap.

There are different ways to pass information out of a function, such as,

  • returning on the stack, as here. Usually this is good for structures which the memory imprint is trivial. div , strtod64 ;
  • passing a pointer to the data that's to be filled. fread , fscanf , snprintf , sprintf , strfmon , strncat , strncpy , strptime , strftime , asctime_r , ctime_r , localtime_r ;
  • keeping a static struct -- this method not re-entrant and overwrites the same data multiple times. It is not thread-safe. asctime , ctime , gmtime , localtime , strtok ;
  • having a type associated with the state that one needs to pass to do operations, FILE * : fopen / fclose , regex_t : regcomp / regfree , or global, errno : perror ;
  • returning an heap-allocated pointer which the user must free. For example, asprintf .

This answer is an alternative to using structs - which is of course valid - you can return multiple value by reference/via a pointer. And answers the main question whether it is possible to return mulitple value from a single function.

#include<stdio.h>

void sum_diff(double a, double b, double* sum, double*diff)
{
    if (sum) // Only assign when we have a valid reference
        *sum = a + b;
    if (diff)
        *diff= a - b;
}

int main() {

    double diff, sum;
    double a = 4, b = 3;

    sum_diff(a, b, &sum, &diff);

    fprintf(stdout, "The sum of %lf and %lf is %lf\n", a, b, sum);
    fprintf(stdout, "The difference of %lf and %lf is %lf\n", a, b, diff);

    return 0;
}

The function sum_diff assigns uses the arguments a , b , sum and diff . a and b are input arguments and sum and diff are the output arguments. Notice that the function checks whether sum and diff are not NULL, this allows the caller to optionally get the difference or sum. This might be handy with more computational intensive calculations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM