How can I pass a generic struct to a function in C? -


i'm beginner in c programming , have doubt pass generic struct function in c.

here have:

typedef struct {     char name[20];     float price; } product;  typedef struct {     char name[20];     int type; } category; 

and want this:

void changename(struct *s, newname[20]) {     strcpy(s->name, newname); } 

if has asked that, please disconsider , sends me issue link.

someone can me?

thanks.

using union

one approach add structure containing union, containing pointers product , category structures, enum identify type of data in struct. union, or pointer it, passed change_name() function.

here example work in c11. uses unnamed union member, not valid c99 code:

#include <stdio.h> #include <string.h>  typedef struct {     char name[20];     float price; } product;  typedef struct {     char name[20];     int type; } category;  typedef struct {     enum { product, category } type;     union {         product *prod;         category *cat;     }; } generic;  void change_name(generic *gen, const char *new_name);  int main(void) {     product prod_a = { .name = "widget", .price = 1.99 };     category cat_a = { .name = "general", .type = 1 };     generic gen_prod_a = { .type = product, .prod = &prod_a };     generic gen_cat_a = { .type = category, .cat = &cat_a };      printf("prod_a.name = %s\n", prod_a.name);     printf("cat_a.name = %s\n", cat_a.name);      change_name(&gen_prod_a, "gadget");     change_name(&gen_cat_a, "specific");      printf("prod_a.name = %s\n", prod_a.name);     printf("cat_a.name = %s\n", cat_a.name);      return 0; }  void change_name(generic *gen, const char *new_name) {     switch (gen->type) {     case product:         strcpy(gen->prod->name, new_name);         break;     case category:         strcpy(gen->cat->name, new_name);         break;     default:         fprintf(stderr, "unknown type in change_name()\n");     } } 

this made work in c99 naming union:

typedef struct {     enum { product, category } type;     union {         product *prod;         category *cat;     } data;                                  // named c99 } generic;  /* ... */  generic gen_prod_a = { .type = product, .data.prod = &prod_a }; generic gen_cat_a = { .type = category, .data.cat = &cat_a };  /* ... */  void change_name(generic *gen, const char *new_name) {     switch (gen->type) {     case product:         strcpy(gen->data.prod->name, new_name);         break;     case category:         strcpy(gen->data.cat->name, new_name);         break;     default:         fprintf(stderr, "unknown type in change_name()\n");     } } 

alternatively, 1 struct type hold enum identifier , union containing product , category structures. approach may seem bit more streamlined:

#include <stdio.h> #include <string.h>  typedef struct {     enum { product, category } type;     union {         struct {             char name[20];             float price;         } prod;         struct {             char name[20];             int type;         } cat;     } data; } record;  void change_name(record *rec, const char *new_name);  int main(void) {     record prod_a = { .type = product };     change_name(&prod_a, "widget");     prod_a.data.prod.price = 1.99;      record cat_a = { .type = category };     change_name(&cat_a, "general");     cat_a.data.cat.type = 1;      printf("prod_a.name = %s\n", prod_a.data.prod.name);     printf("cat_a.name = %s\n", cat_a.data.cat.name);      change_name(&prod_a, "gadget");     change_name(&cat_a, "specific");      printf("prod_a.name = %s\n", prod_a.data.prod.name);     printf("cat_a.name = %s\n", cat_a.data.cat.name);      return 0; }  void change_name(record *rec, const char *new_name) {     switch (rec->type) {     case product:         strcpy(rec->data.prod.name, new_name);         break;     case category:         strcpy(rec->data.cat.name, new_name);         break;     default:         fprintf(stderr, "unknown type in change_name()\n");     } } 

using type-generic macro

both of above approaches little bit awkward. solution, available c11 only, use _generic keyword in type-generic macro. here, functions written each expected data type, , macro selects function definition used based on type. virtue of approach new types added, new functions , updates type-generic macro needed handle them.

#include <stdio.h> #include <string.h>  #define change_name(s, n) _generic ((s),                                \                                     prod_ptr: change_name_prod,         \                                     cat_ptr: change_name_cat            \                                    )((s), (n))  typedef struct {     char name[20];     float price; } product;  typedef struct {     char name[20];     int type; } category;  typedef product *prod_ptr; typedef category *cat_ptr;  void change_name_prod(product *prod, const char *new_name); void change_name_cat(category *cat, const char *new_name);  int main(void) {     product prod_a = { .name = "widget", .price = 1.99 };     category cat_a = { .name = "general", .type = 1 };      printf("prod_a.name = %s\n", prod_a.name);     printf("cat_a.name = %s\n", cat_a.name);      change_name(&prod_a, "gadget");     change_name(&cat_a, "specific");      printf("prod_a.name = %s\n", prod_a.name);     printf("cat_a.name = %s\n", cat_a.name);      return 0; }  void change_name_prod(product *prod, const char *new_name) {     strcpy(prod->name, new_name); }  void change_name_cat(category *cat, const char *new_name) {     strcpy(cat->name, new_name); } 

all of above programs have same output:

prod_a.name = widget cat_a.name = general prod_a.name = gadget cat_a.name = specific 

Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -