sffc
sffc

Reputation: 6424

Can you allow one of a few types of pointers as an argument without void*?

In plain , I have a situation where I would like to allow a function to accept multiple types of pointers. To illustrate my situation, here could be one use case:

void myfunction([int* or char*] value) {
    *value = 0xdd;  // safe since value is at least as big as a char*
}

And here is another:

#define MAGIC 0xabcdef0
typedef struct {
    int magic;
    char* content;
} MyStruct;

void myfunction([int* or MyStruct*] value) {
    if (*value != MAGIC) {
        printf("Got an int\n");
    } else {
        printf("Got a MyStruct\n");
    }
}

// example:
int input1 = 0;
MyStruct input2 = { MAGIC, "hello world" };
myfunction(input1);  // "Got an int"
myfunction(input2);  // "Got a MyStruct"

Both of these situations could be made possible with a void* parameter type, but that would in effect allow any type of pointer to be passed in without a compile error. Is there a way to restrict the function to accept only a specific subset of pointer types?

Upvotes: 2

Views: 89

Answers (4)

gsamaras
gsamaras

Reputation: 73366

No, use void* and then cast.

One could think that I can use a void* and then check about the casting inside the function, and if not the expected type, raise an error, but no, you cannot do that either, since void* loses all its type information.

Damn I am writing just before going into the shower. I couldn't resist! BRB :) -- OK, turns out R..'s answer from the future is the correct one! ;)

Upvotes: 0

Matheus Nogueira
Matheus Nogueira

Reputation: 96

As Houman pointed out, you can use a union to do the job, however, you still have the problem that you must identify the type that is set in the union type. You can solve that using an enum to identify the type inside your function.

union myUnion {
    int* intPointer,
    MyStruct* myStructPointer
};

enum typeEnum {
    INT,
    MYSTRUCT
};

void myfunction(union myUnion union, enum typeEnum type) {
    if (type == INT)
         // you got an integer
    else if (type == MYSTRUCT)
         // you got a struct
    // You can add future additions here
 }

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215257

If you can use features that are new in C11, the _Generic keyword can solve your problem:

void myfunction(void *value) {
    // ...
}
#define myfunction(x) myfunction( \
    _Generic((x), char *: (x), int *: (x)) )

Upvotes: 2

M.M
M.M

Reputation: 141586

You could do this:

void myfunction(void *s)
{
    if ( *(int *)s == MAGIC )
    {
        MyStruct *p = s;
        printf("%s\n", p->content);
    }
}

However this design makes it easy to write buggy code that the compiler will not catch for you, so I would recommend coming up with a slightly different design (e.g. tagged unions).

Upvotes: 0

Related Questions