LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-12-2010, 07:28 PM   #1
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Generics in C?


I was thinking about how to make a dynamic array in C, and I thought that it would be much better if it could accept any data type. Is this possible? Of course I thought about void pointers, but how do I store the actual data?
 
Old 02-12-2010, 08:11 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
I was thinking about how to make a dynamic array in C, and I thought that it would be much better if it could accept any data type. Is this possible? Of course I thought about void pointers, but how do I store the actual data?
Use smart enough preprocessor - if you want compile time type checking.
 
Old 02-13-2010, 12:27 PM   #3
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
But what if the generic code is precompiled, and the program that uses it just has the header?
 
Old 02-13-2010, 01:13 PM   #4
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, MTK358 -

I really don't understand your perverse fascination with taking C++ constructs and trying to implement them verbatim in C. In previous posts, it was C++ style inheritance. In this post, C++ style templates. I mean, you certainly *can*. In the same sense you can certainly eat stringbeans through your nose (if you try hard enough). But *why*????

Anyway: let's say you want a "generic linked list" (for example) in C. You want the *same* code to be able to handle *different* types, but you *also* want to "remember" the type as you store it in the list.

Easy. Many alternatives.

But arguably the simplest, most straightforward approach would be:

1. Have your linked list store pointers (duh!)
2. Always store a pointer to a "struct" (never a "bare primitive" like char or double)
3. Your struct contains a "tag" identifying the "type"
4. The same .h header that defines your struct also defines your "tags" (e.g. an enum of "known types").

IMHO .. PSM

PS:
alunduil and I posted almost exactly the same time. A union is of structs would also work, but I think you'd also probably need the tag, to retain knowledge of the original "type".

Last edited by paulsm4; 02-13-2010 at 01:20 PM.
 
Old 02-13-2010, 01:16 PM   #5
alunduil
Member
 
Registered: Feb 2005
Location: San Antonio, TX
Distribution: Gentoo
Posts: 684

Rep: Reputation: 62
In line with the previous post look into the union structure. It will allow you to handle mixed types in your list as well.

Regards,

Alunduil
 
Old 02-13-2010, 09:05 PM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
But what if the generic code is precompiled, and the program that uses it just has the header?
Perform web search on

RTTI

- and yes, you reinventing C++ or whatever.
 
Old 02-15-2010, 09:08 PM   #7
Dan04
Member
 
Registered: Jun 2006
Location: Texas
Distribution: Ubuntu
Posts: 207

Rep: Reputation: 37
A direct emulation of C++ templates would look something like:

Code:
#define DEF_ARRAY_TYPE(ARRAY_TYPE, ITEM_TYPE) \
   typedef struct { \
      size_t capacity; \
      site_t length; \
      ITEM_TYPE* data; \
   } ARRAY_TYPE; \
   ARRAY_TYPE* ARRAY_TYPE##new(void) { \
      ARRAY_TYPE* arr = malloc(sizeof(ARRAY_TYPE)); \
      arr->capacity = DEFAULT_CAPACITY; \
      arr->length = 0; \
      arr->data = calloc(DEFAULT_CAPACITY, sizeof(ITEM_TYPE)); \
      return arr; \
   } \
   void ARRAY_TYPE##_delete(ARRAY_TYPE* arr) \
   { \
      free(arr->data); \
      free(arr); \
   } \
   ITEM_TYPE ARRAY_TYPE##_getitem(ARRAY_TYPE* arr, size_t index) \
   { \
      return arr->data[index]; \
   } \
   void ARRAY_TYPE##_setitem(ARRAY_TYPE* arr, size_t index, ITEM_TYPE value) { \
      arr->data[index] = value; \
   } \
   // ...

DEF_ARRAY_TYPE(IntArray, int);
If you choose this approach, you might want to write a C pre-preprocessor.
 
Old 02-16-2010, 07:07 AM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Dan04 View Post
A direct emulation of C++ templates would look something like:

Code:
#define DEF_ARRAY_TYPE(ARRAY_TYPE, ITEM_TYPE) \
   typedef struct { \
      size_t capacity; \
      site_t length; \
      ITEM_TYPE* data; \
   } ARRAY_TYPE; \
   ARRAY_TYPE* ARRAY_TYPE##new(void) { \
      ARRAY_TYPE* arr = malloc(sizeof(ARRAY_TYPE)); \
      arr->capacity = DEFAULT_CAPACITY; \
      arr->length = 0; \
      arr->data = calloc(DEFAULT_CAPACITY, sizeof(ITEM_TYPE)); \
      return arr; \
   } \
   void ARRAY_TYPE##_delete(ARRAY_TYPE* arr) \
   { \
      free(arr->data); \
      free(arr); \
   } \
   ITEM_TYPE ARRAY_TYPE##_getitem(ARRAY_TYPE* arr, size_t index) \
   { \
      return arr->data[index]; \
   } \
   void ARRAY_TYPE##_setitem(ARRAY_TYPE* arr, size_t index, ITEM_TYPE value) { \
      arr->data[index] = value; \
   } \
   // ...

DEF_ARRAY_TYPE(IntArray, int);
If you choose this approach, you might want to write a C pre-preprocessor.
Further developing the approach - such generic things depend in reality not on type, but rather on sizeof(type). So a smarter preprocessor can really help - it will create new functions not for every new type, but for every new sizeof(type).

In a code of mine I am importing into Perl "C" numeric macros by creating a small test program which printf's the macro to be imported in the format of my choosing. I.e. the smart preprocessor can be made "C" types aware in such a manner.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
SYSERR(root): hash map "generics": missing map file /etc/mail/genericstable.db? singying304 Linux - Networking 4 02-28-2005 06:49 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:31 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration