0
votes

I have 2 data structures as following:

struct data_type{
    char name[20]; 
    int (*check_equal)(void* a, void* b);
}

and

struct attr_data{
    int data_type; 
    void* (*get_func)(void* record); //Not sure about prototype of this function
}

The first data structure is actually a structure used for different logical datatypes like string and int(c datatypes of short and int would come under "int" logical type). So, I have an array of this data_type struct with 2 elements in it: one with name as string and other one with name as integer. "check_equal" function for string is just a call to function strcmp() using args a and b given, which are typecasted to char*. Similar is case with the check_equal function for "integer" element. But notice here that in this implementation, the "check_equal" function would require pointers to 2 integers passed. The second data structure actually is a meta data for any other data structure like:

struct abc{
    char* a;
    int b;
 }

For every member variable in struct abc, supposed I maintain an instance of struct attr_data in some array. Ideally a get function for some member variable should always return value of that member variable and not a pointer to that. Thus get function for member a in struct abc should return char* but that for b, should return an int. Now I need to use these get_funcs to directly pass an argument to the check_equal function of struct data_type. But since prototype of check_equal function is (void*,void*), using this get_func fails. Can anyone help me out deciding prototypes of function pointers used here? Can someone help understand the issues behind typecasting int to void*?

2
You should use a struct with a enum which hold the data type and a union for the actual data. Then pass this structure as argument and depending on the enum, perform the appropriate operation. That's actually how high level languages implement dynamic typing - z̫͋
That seems interesting. Can you elaborate more with some example? - labyrinth

2 Answers

0
votes

enum e{CHAR, INT, FLOAT, DOUBLE, CHARP, INTP, ......}

you can use these data types as a reference and using switch case you can do desired operation with with different data type.

0
votes

Here's a simple example where struct data can either hold a string or an integer.

struct data {
    enum {
        INT,
        STRING
    } type;
    union {
        int integer;
        char* string;
    } value;
};

Now you can try to do some comparison:

#include <stdio.h>
#include <string.h>

char str1[] = "test";
char str2[] = "test";
char str3[] = "another test";

int check_equal(struct data *v1, struct data *v2)
{
    if(v1->type == INT && v2->type == INT) {
        return v1->value.integer == v2->value.integer;
    }
    else if(v1->type == STRING && v2->type == STRING) {
        return strcmp(v1->value.string, v2->value.string) == 0;
    }
    else return 0;
}


int main(void)
{
   struct data var1, var2, var3, var4, var5, var6;

   var1.type = INT;
   var2.type = INT;
   var3.type = INT;
   var1.value.integer = 3;
   var2.value.integer = 3;
   var3.value.integer = 4;

   var4.type = STRING;
   var5.type = STRING;
   var6.type = STRING;

   var4.value.string = str1;
   var5.value.string = str2;
   var6.value.string = str3;

   printf("var1 = var2 : %d \n",check_equal(&var1,&var2)); // 1
   printf("var1 = var3 : %d \n",check_equal(&var1,&var3)); // 0

   printf("var4 = var5 : %d \n",check_equal(&var4,&var5)); // 1
   printf("var4 = var6 : %d \n",check_equal(&var4,&var6)); // 0

   return EXIT_SUCCESS;
}