midugh
midugh

Reputation: 658

Is there any way to return any type in C functions without using void pointers?

I'm quite new to C development and I would like to know if there's any way to return any type in a C function as this java code would:

public static Object returnAnyType(Object anyType){
    //example useless code
    return anyType;
}
public static void main(String[] args) {
    System.out.println(returnAnyType('c'));
    // outs 'c'
}

I know there's a way to return any type of pointers as void pointers in C :

void* returnAny(void* anyType){
    //example useless code
    return anyType;
}

void main(){
    char ch = 'c';
    printf("%c\n", *(char*)returnAny(&ch));
    // outs 'c'
}

and I would like to know if it's possible to have the same above java code in C without having to use void pointers either in return types and in parameters. So far I've tried using void for return types but my compiler doesn't accept return statement without return type.

Upvotes: 1

Views: 576

Answers (2)

ryyker
ryyker

Reputation: 23218

Yes. There is a way to return [one of a selection of] type[s] in C functions without using void pointers. A struct that is defined to contain two members,

  • A union defined with all of the types of interest.
  • An enum with values indicating which type is being passed.

Because C is not an object oriented language such as Java or Python, the methods used to accomplish what you want in C are not as elegant as what you might in the other laguages, but I have used this method in C, and gets the job done:

typedef enum {
   CHAR,
   INT,
   DOUBLE,
   UCHAR,
   UINT,
   ...  //etc etc etc
} TYPE;

typedef union  {
   char char_var;
   int  int_var;
   double dble_var;
   unsigned char uchar_var;
   unsigned int uint_var;
   ... /// etc etc
}VAR;

typedef struct {
   VAR var;  // one of the types contained in union
   TYPE type;  // corresponding emum value indicating type sent
} DATA;

DATA data *pData;

This prototype can be used to pass any type (defined in the struct and union above):

DATA * returnAnyType(DATA *data);

Once the function processes its input and returns, the values returned can be fed into a printf statement via a switch statement. A very bare bones example illustrates:

int main(void)
{
    DATA dataout = {12, INT};

    DATA *datain = returnAnyType(&dataout);
    if(datain)
    {
        switch( datain->type)  {
            case (CHAR):
                printf("Type returned is \"char\", its value is: %c", datain->var.char_var);
                break;
            case (INT):
                printf("Type returned is \"int\", its value is: %d", datain->var.int_var);
                break;
            // and so on
        }
        free(datain); memory created in called function, free here.
    }

    return 0;
}

DATA * returnAnyType(const DATA *data)
{
    /////////////////////////////////////////////////////////////////////// 
    // Do what ever manipulation is needed with "data" in this section, 
    // then package into pD for the return trip
    /////////////////////////////////////////////////////////////////////

    DATA *pD = calloc(1, sizeof *pD);//create pointer instance for return
                                     //!! must be free in caller !!
    if(pD)
    {
        pD->type = data->type;
        switch (pD->type) {
            case CHAR:
                pD->var.char_var = data->var.char_var;
                break;
            case INT:
                pD->var.int_var = data->var.int_var;
                break;
            // and so on ...
        }
    }

    return pD;//free in caller function
}

Upvotes: 5

Paul92
Paul92

Reputation: 9062

In C is very hard to express relationships between objects. An object is simply a specific memory layout, and thus there is no way of casting between them. You can define conversion functions, but that's pretty much it.

Since there is no concept of relation between objects, there also is no object such as Java's Object.

Therefore, not only is impossible to have a function that can return something more general, but is impossible to define a function that can return multiple types.

void* works only because any pointer can be converted to void*, not that is special in any sense.

Upvotes: 5

Related Questions