Can I get "macro polymorphism" in C - c

The type of polymorphism I'm after is this:
suppose I have a macro called draw(), and I have 2 structs, one called circle and the other called square. Is is possible to somehow do something like this:
#define draw() // can I get the text that's behind the macro?
//then maybe, with _Generic achieve this?
void draw_circle(struct circle);
void draw_square(struct square);
struct circle c;
struct square s;
c.draw();//draw is a macro. this time it is supposed to expand to draw_circle(c);
s.draw();//supposed to expand to draw_square(s);
EDIT_1: this is what I have so far, after reading your answers.
//raw_array.h
#pragma once
#include <stdint.h>
#include <stdlib.h>
#define byte uint8_t
#define _GET_OVERRIDE(_1, _2, _3, NAME, ...) NAME
/*#define init_impl(...) _GET_OVERRIDE(__VA_ARGS__, \
init_impl3, init_impl2, init_impl1)(__VA_ARGS__)
#define init( name, ... ) (raw_array * (name); init_impl( (name), __VA_ARGS__))*/
#define array_init_impl(...) _GET_OVERRIDE(__VA_ARGS__, init_array_impl3, init_array_impl2, init_array_impl1)(__VA_ARGS__)
///<summary>creates a variable of type raw_array with name as an identifier, and initializes based on the parameters</summary>
#define RAW_ARRAY( name, ... ) raw_array (name); array_init_impl( (&name), __VA_ARGS__)
typedef struct indexable_memory_block_struct
{
raw_array * _self;
byte * bytes;
size_t element_size;
size_t number_of_elements;
} raw_array;
///<summary>starts the an empty raw_array. only element_size is set.</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=element_size>the size of the elements in this raw_array</param>
void init_impl1 ( raw_array * r_arr, size_t element_size )
{
r_arr = malloc ( sizeof ( raw_array ) );
r_arr->element_size = element_size;
r_arr->number_of_elements = 0;
r_arr->bytes = NULL;
r_arr->_self = r_arr;
}
///<summary>
///starts the raw_array an empty. byte with its bytes allocated
///to their default value (0).
///</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=element_size>the size of the elements in this raw_array</param>
///<param name=number_of_elements>the number of elements in the array</param>
void init_impl2 ( raw_array * r_arr, size_t element_size, size_t number_of_elements )
{
r_arr = malloc ( sizeof ( raw_array ) );
r_arr->element_size = element_size;
r_arr->number_of_elements = number_of_elements;
r_arr->bytes = calloc ( number_of_elements, element_size );
r_arr->_self = r_arr;
}
///<summary>
///starts the raw_array copying its contents from a normal array.
///</summary>
///<param name=r_arr>the raw_array to be initialized</param>
///<param name=arr>the normal C array whose contents will be copied to this raw_array</param>
///<param name=element_size>the size of the elements in this raw_array</param>
///<param name=number_of_elements>the number of elements in the array</param>
void init_impl3 ( raw_array * r_arr, const void * const arr, size_t size_of_element, size_t number_of_elements )
{
r_arr->bytes = malloc ( size_of_element * number_of_elements );
memcpy ( r_arr->bytes, arr, size_of_element * number_of_elements );
r_arr->element_size = size_of_element;
r_arr->number_of_elements = number_of_elements;
r_arr->_self = r_arr;
}
there are other parts, but these are the ones currently being ported to this new syntax. Now main:
int main ( int argc, char * argv[] )
{
int data[30];
//line bellow has a compilation error: *expected a ')'*
init ( r_arr, data, sizeof ( int ), 30 );
}
what does it mean expected a ')'
could you guys check out the macro syntax?
About _Generic, I learned about it today, and I'll use it if it's useful, for sure.
EDIT_2: found a gross error, will be fixing it and editing again. Visual Studio is updating (12GB...) So I can't build anything at the moment. [mini-edit]: Guess I fixed the gross error at least. [mini-edit] another very bizarre error in my code, I stringifyed the name token, wth?! corrected now.
EDIT_3: having slept and having VS operational again, I fixed the macros, will edit them and comment out the wrong code. Now I need to the circle.draw() behaviour... any ideas?

Besides #LirooPierre s approach, you could also use C11 Generics. Yes you heard right, C has generics now.
Consider this example:
#include <stdio.h>
#define draw(X) _Generic((X), \
struct circle: draw_circle, \
struct square: draw_square \
)(X)
struct circle{};
struct square{};
void draw_circle(struct circle a)
{
printf("Drawing a circle\n");
}
void draw_square(struct square a)
{
printf("Drawing a square\n");
}
int main(void)
{
struct square a;
draw(a); // "Drawing a square"
}
But even though it should be portable, it sadly is not. M$ Compiler doesn't implement them, but clang and gcc do.

You can really only achieve what want in c with function pointers
struct shape {
{
void (*draw)(struct shape);
};
void draw_circle(struct shape);
void draw_square(struct shape);
#define CIRCLE(c) struct shape c; c.draw = &draw_circle;
#define SQUARE(s) struct shape s; s.draw = &draw_square;
Now you can do something like this:
CIRCLE(c)
SQUARE(s)
c.draw(c);
s.draw(s);
You could add a draw macro too if you don't like the c.draw(c) syntax.
#define DRAW(shape) shape.draw(shape)
DRAW(c);
DRAW(s);

Yes it is possible !
You have to create a pointer on a function in your struct like this:
typedef void (*t_draw)(struct circle); //create a new type called t_draw
struct circle {
t_draw draw;
}
Now in your code you have to assign a function in your struct:
struct circle c;
c.draw = &draw_circle;
and call it by using:
c.draw(/*your args*/);
Create the second structure square like the first and it should be OK !

Related

Cmocka: checking a structure passed as a parameter

Let's say that I declare a C struct called foo, which has an int field called bar and a char * called baz.
How do I use the Cmocka expect_ and check_expected macros to check that the structure passed was correct and both fields have the expected values? If there is an example in the documentation, I missed it.
[Update] Perhaps I can use expect_check()? But I can't find an example :-(
Use expect_memory(...) and check_expected(...):
Example:
I assume you have a function under test fut which calls a subfunction subfunc. Your struct looks like this:
typedef struct foo_s {
int bar;
int baz;
} foo;
And your test driving function could look like this:
void test(void **state) {
foo myfoo = {
.bar = 42,
.baz = 13,
};
expect_memory(subfunc, param, &myfoo, sizeof(foo));
fut();
}
And the subfunctions could look like this:
void subfunc(foo *param){
check_expected(param);
}
Comparing the memory of the struct might work in most cases, however if your compiler puts some filler bytes in there, you have some bytes which you have no controll over and might have random values. This means that your test might not alway yield the same result, which can lead to very annoying debugging session.
For example if you have a struct like this:
typedef struct {
uint8_t c;
uint32_t i;
} tSomeStruct
You might think that the c and i are put right next to each other and sizeof( tSomeStruct ) returns 5. However if you try this out you would be surprised that it is more likely that sizeof( tSomeStruct ) actually returns 8. This is because of the mentioned filler bytes. You do not know what the values of these other bytes are. You can work around this by memsetting your structs to 0 before using them, however this is a little bit hacky and does not work in every case.
To compare structs in a clean way cmocka you can use expect_check( ... ) and check_expected( ... ). This gives you the possibility to write your own comparisson function.
Here is an example on how to use this ( Modified this example: Cmocka Gitlab )
typedef struct {
char c;
int i;
} tSomeStruct;
void mock_function( tSomeStruct* param )
{
check_expected(param)
}
/* return 1 = true, return 0 = false */
int my_int_equal_check(const LargestIntegralType value,
const LargestIntegralType check_value_data)
{
tSomeStruct* cast_value = ( tSomeStruct* ) value;
tSomeStruct* cast_check_value_data = ( tSomeStruct* ) check_value_data;
if ( ( cast_value->c == cast_check_value_data->c )
&& ( cast_value->i == cast_check_value_data->i ) ) {
return 1;
}
return 0;
}
void mytest(void **state)
{
tSomeStruct struct = {
.c = 'c',
.i = 'i',
}
expect_check(mock_function, param, my_int_equal_check, &struct);
}
I am not sure however if this is possible, if you do not pass your struct as a pointer to your function, as the check function only takes LargestIntegralType.
I recently found out that you can use the struct members inside the check_expected and expect_value:
typedef struct
{
int a;
float b;
} SomeStruct_t;
void mocked_function(SomeStruct_t* s)
{
check_expected(s->a);
check_expected(s->b);
}
void someTest(void **state)
{
expect_value(mocked_function, s->a, 3);
expect_value(mocked_function, s->b, 7.2);
// ...
}

Let a macro count its invocations

I've a huge C project with a module reading and managing configuration data. If I have to add a new configuration parameter, I'll have to edit several functions, e.g. as pseudo-code:
void read_configuration(config *c) {
read_param("p1", c->p1);
read_param("p2", c->p2);
read_param("p3", c->p3);
/* ... */
}
void dump_configuration(config *c) {
dump_param("p1", c->p1);
dump_param("p2", c->p2);
dump_param("p3", c->p3);
/* ... */
}
Is there a way to ensure by macro at compile time, that each location has at least the same count of parameters? I thought of making dump_param some kind of macro counting the invocations and then add something like
#if nr_read != nr_dump
#error "You forgot something, idiot!"
#endif
at the end of the module. I can't find a method to make the macro count its invocations, though...
Since the list of parameters is the same in both functions, how about factoring that out and avoid any possible mismatch ?
Using X-macros
#define X_CONFIG_PARAMS(config) \
X("p1", (config).p1) \
X("p2", (config).p2) \
X("p3", (config).p3)
void read_configuration(config *c) {
#define X(name, param) read_param(name, &param);
X_CONFIG_PARAMS(*c)
#undef X
}
void dump_configuration(config *c) {
#define X(name, param) dump_param(name, &param);
X_CONFIG_PARAMS(*c)
#undef X
}
Using function pointers
void alter_config(config *c, void(*func)(char const *name, Param *param)) {
func("p1", &c->p1);
func("p2", &c->p2);
func("p3", &c->p3);
}
void read_configuration(config *c) {
alter_config(c, read_param);
}
void dump_configuration(config *c) {
alter_config(c, dump_param);
}
Using an array and offsetof
struct param_info {
char const *name;
size_t config_offs;
};
param_info allParams[] = {
{"p1", offsetof(config, p1)},
{"p2", offsetof(config, p2)},
{"p3", offsetof(config, p3)}
};
void read_configuration(config *c) {
size_t paramCount = sizeof allParams / sizeof *allParams;
for(size_t i = 0; i < paramCount; ++i) {
Param *p = (Param*)((char*)config + allParams[i].config_offs);
read_param(allParams[i].name, p);
}
}
void dump_configuration(config *c) {
size_t paramCount = sizeof allParams / sizeof *allParams;
for(size_t i = 0; i < paramCount; ++i) {
Param *p = (Param*)((char*)config + allParams[i].config_offs);
dump_param(allParams[i].name, p);
}
}
I would rather let the preprocessor write the code in the first place.
It could look something like this:
Define the list of parameters in a separate file, say parameters.inc:
PARAM (p1)
PARAM (p2)
...
Then in the source code locally define the macro PARAM as required and let the preprocessor include and expand the contents of parameters.inc:
void read_configuration(config *c) {
#define PARAM(NAME) read_param(#NAME, c->NAME);
#include "parameters.inc"
#undef PARAM
}
void dump_configuration(config *c) {
#define PARAM(NAME) dump_param(#NAME, c->NAME);
#include "parameters.inc"
#undef PARAM
}
I don't think you can do this at compile time without ugly hacks.
What you could do: add a test to your test suite which replaces the header that contains the read_param() and dump_param() macros so they generate code which only updates a counter. Then, in the main() function of that test, place an assertion that compares both counters and fails if they're not equal.
You do have a test suite and run it at compile time, right? ;-)
However, I do agree with the comment that it's probably better to do this differently. In an approach called "table-driven programming", you turn the macro definition and data definition on their head (that is, you have the #define in your .c file and the use of the macro in the header rather than the other way around), you don't have this problem. Poul-Henning Kamp, of FreeBSD fame, explains very well how to that here.

External Functions and Parameter Size Limitation (C)

I am very much stuck in the following issue. Any help is very much appreciated!
Basically I have a program wich contains an array of structs and I am getting a segmentation error when I call an external function. The error only happens when I have more than 170 items on the array being passed.
Nothing on the function is processed. The program stops exactly when accessing the function.
Is there a limit for the size of the parameters that are passed to external functions?
Main.c
struct ratingObj {
int uid;
int mid;
double rating;
};
void *FunctionLib; /* Handle to shared lib file */
void (*Function)(); /* Pointer to loaded routine */
const char *dlError; /* Pointer to error string */
int main( int argc, char * argv[]){
// ... some code ...
asprintf(&query, "select mid, rating "
"from %s "
"where uid=%d "
"order by rand()", itable, uid);
if (mysql_query(conn2, query)) {
fprintf(stderr, "%s\n", mysql_error(conn2));
exit(1);
}
res2 = mysql_store_result(conn2);
int movieCount = mysql_num_rows(res2);
// withhold is a variable that defines a percentage of the entries
// to be used for calculations (generally 20%)
int listSize = round((movieCount * ((double)withhold/100)));
struct ratingObj moviesToRate[listSize];
int mvCount = 0;
int count =0;
while ((row2 = mysql_fetch_row(res2)) != NULL){
if(count<(movieCount-listSize)){
// adds to another table
}else{
moviesToRate[mvCount].uid = uid;
moviesToRate[mvCount].mid = atoi(row2[0]);
moviesToRate[mvCount].rating = 0.0;
mvCount++;
}
count++;
}
// ... more code ...
FunctionLib = dlopen("library.so", RTLD_LAZY);
dlError = dlerror();
if( dlError ) exit(1);
Function = dlsym( FunctionLib, "getResults");
dlError = dlerror();
(*Function)( moviesToRate, listSize );
// .. more code
}
library.c
struct ratingObj {
int uid;
int mid;
double rating;
};
typedef struct ratingObj ratingObj;
void getResults(struct ratingObj *moviesToRate, int listSize);
void getResults(struct ratingObj *moviesToRate, int listSize){
// ... more code
}
You are likely blowing up the stack. Move the array to outside of the function, i.e. from auto to static land.
Another option is that the // ... more code - array gets populated... part is corrupting the stack.
Edit 0:
After you posted more code - you are using C99 variable sized array on the stack - Bad IdeaTM. Think what happens when your data set grows to thousands, or millions, of records. Switch to dynamic memory allocation, see malloc(3).
You don't show us what listsize is, but I suppose it is a variable and not a constant.
What you are using are variable length arrays, VLA. These are a bit dangerous if they are too large since they usually allocated on the stack.
To work around that you can allocate such a beast dynamically
struct ratingObj (*movies)[listSize] = malloc(sizeof(*movies));
// ...
free(movies);
You'd then have in mind though that movies then is a pointer to array, so you have to reference with one * more than before.
Another, more classical C version would be
struct ratingObj * movies = malloc(sizeof(*movies)*listsize);
// ...
free(movies);

C automatic-expandable array of pointers

QUESTION ANSWERED AT END OF PAGE. FULLY WORKING CODE.
Hello, I would like to do in C what I have asked in the title, however, I don't know how to accomplish it. I have done this in C++ thanks to templates but à la C. Here is the fully functional C++ code: List.h (simple database)
*I wonder now if with void pointers I can emulate the code. The problem is that I've seen a link stating that void * should be avoided because it can cause more trouble than it can solve.
Basically it is a "smart-array" that stores pointers to the variables themselves.
If I know the size of each pointer and the size of each structure pointed to, simple mallocs and reallocs should do right?
typedef struct
{
void **list;
// internal
int last_item_index;
size_t element_size; // size of each pointer
int elements; // number of currently allocated elements
int total_size; // >= #elements so that we don't have to always call malloc
int tweak_request_size; // each time the list grows we add this # of elements
} List;
// a shot at an addCopy function
// it deepcopies the object you pass in
List_addCopy(List *db, void *ptr_to_new_element)
{
... // grow **list
// alloc and copy new element
db->list[db->last_item_index+1] = malloc(element_size); // WORKS?
// HOW TO COPY THE ELEMENT TO HERE IF IT IS A STRUCTURE FOR INSTANCE???
...
}
or
// a shot at an assign function
// (allocate the elements yourself then pass the pointer to the List)
List_assign(List *db, void *ptr_to_new_element)
{
db->List = realloc(db->List, element_size*(elements+tweak_request_size));
db->List[db->last_item_index+1] = ptr_to_new_element;
}
// Usage example
List db; // our database
struct funky *now = (funky*)malloc(sizeof(funky));
funky->soul = JamesBrown;
List_addCopy(db, funky);
if (list[0]->soul == JamesBrown)
puts("We did It! :D");
If I alloc everything outside and just pass the pointers to the List I guess the only problem is the void **.
Is List_add possible? Only with callbacks that do the alloc of the element and / or copy it?
Is List_assign possible? I don't want to have a lot of work and end up with unreliable software.
Thanks a lot and sorry for the convolution in the writing :p
You can avoid void* with something like this:
#include <stdio.h>
#include <stdlib.h>
#define List(T) \
typedef struct { \
T** items; \
int count; \
} List_ ## T ;\
\
List_ ## T * List_ ## T ## _New() { \
List_ ## T * list = (List_ ## T *) malloc(sizeof(List_ ## T)); \
list->count = 0; \
return list; \
} \
\
void List_ ## T ## _Add(List_ ## T *list, T * data) { \
printf("%d\n", ++list->count); \
} \
void List_ ## T ## _Del(List_ ## T *list, int index) { \
printf("%d\n", --list->count); \
}
/* define just one list per type */
List(int);
List(double);
int main()
{
int a, b, c;
double d, e;
List_int *l1;
List_double *l2;
l1 = List_int_New();
List_int_Add(l1, &a);
List_int_Add(l1, &b);
List_int_Add(l1, &c);
List_int_Del(l1, 0);
List_int_Del(l1, 0);
List_int_Del(l1, 0);
free(l1);
l2 = List_double_New();
List_double_Add(l2, &d);
List_double_Add(l2, &e);
List_double_Del(l2, 0);
List_double_Del(l2, 0);
free(l2);
return 0;
}
That's a poor man's template =)
I've used Trinidad's method since I wasn't sure void ** would work and it's pretty nice xD
It works perfectly but it is complicated to avoid circular dependencies (including a header in another that results in "multiple reference") without encumbering too much the interface, so I gave up that approach although I've uploaded it too #SourceForge, then I made everything again, this time with void pointers and it works perfectly ;) No worrying about including a header twice, etc. Just works.
Btw, here's the link, use it at your liking: List - the smart && generic container
In any doubt use the help forums, when I have time I'll document it, but for now I'm using it for my projects.

A good C equivalent of STL vector?

I've noticed that at several places in our code base we use dynamically expanding arrays, i.e. a base array coupled with an element counter and a "max elements" value.
What I want to do is replace these with a common data structure and utility functions, for the usual object-oriented reasons.
The array elements can be either basic data types or structs, I need fast random access to the elements, and preferably a type-safe implementation.
So, basically, what I would like to use is an STL vector, but the code base is restricted to C89 so I have to come up with something else :-)
I gave it some thought and whipped up this initial draft, just to show what I'm aiming at:
/* Type-safe dynamic list in C89 */
#define list_declare(type) typedef struct _##type##_list_t { type * base_array; size_t elements; size_t max_size; } type##_list_t
#define list(type) type##_list_t
#define list_new(type, initial_size) { calloc(initial_size, sizeof(type)), 0, initial_size }
#define list_free(list) free(list.base_array)
#define list_set(list, place, element) if ( list.elements < list.max_size ) { list.base_array[place] = element; } else { /* Array index out of bounds */ }
#define list_add(list, element) if ( list.elements < list.max_size ) { list.base_array[list.elements++] = element; } else { /* Expand array then add */ }
#define list_get(list, n) list.base_array[n]
/* Sample usage: */
list_declare(int);
int main(void)
{
list(int) integers = list_new(int, 10);
printf("list[0] = %d\n", list_get(integers, 0));
list_add(integers, 4);
printf("list[0] = %d\n", list_get(integers, 0));
list_set(integers, 0, 3);
printf("list[0] = %d\n", list_get(integers, 0));
list_free(integers);
return EXIT_SUCCESS;
}
...however, there must be someone else who has done this before. I'm aware of the FreeBSD sys/queue.h implementation of a similar concept for some different queues, but I can't find anything like that for arrays.
Is anyone here any wiser?
glib provides an GArray type, which implements a dynamically growing array. If you can use external 3rd party libraries, glib is almost always a good choice as "standard" library for C. It provides types for all basic data structures, for unicode strings, for date and time values, and so on.
here a simple vector-replacement, its ONE function for all, its strictly C89 and threadsafe;
libs are too difficult for me, i use my own;
no performance, but easy to use
/* owner-structs too */
typedef struct {
char name[20],city[20];
int salary;
} My,*Myp;
typedef char Str80[80];
/* add here your type with its size */
typedef enum {SPTR,INT=sizeof(int),DOUBLE=sizeof(double),S80=sizeof(Str80),MY=sizeof(My)} TSizes;
typedef enum {ADD,LOOP,COUNT,FREE,GETAT,GET,REMOVEAT,REMOVE} Ops;
void *dynarray(char ***root,TSizes ts,Ops op,void *in,void *out)
{
size_t d=0,s=in?ts?ts:strlen((char*)in)+1:0;
char **r=*root;
while( r && *r++ ) ++d;
switch(op) {
case ADD: if( !*root ) *root=calloc(1,sizeof r);
*root=realloc(*root,(d+2)*sizeof r);
memmove((*root)+1,*root,(d+1)*sizeof r);
memcpy(**root=malloc(s),in,s);
break;
case LOOP: while( d-- ) ((void (*)(char*))in)((*root)[d]); break;
case COUNT: return *(int*)out=d,out;
case FREE: if(r) {
++d; while( d-- ) realloc((*root)[d],0);
free(*root);*root=0;
} break;
case GETAT: { size_t i=*(size_t*)in;
if(r && i<=--d)
return (*root)[d-i];
} break;
case GET: { int i=-1;
while( ++i,d-- )
if( !(ts?memcmp:strncmp)(in,(*root)[d],s) )
return *(int*)out=i,out;
return *(int*)out=-1,out;
}
case REMOVEAT: { size_t i=*(size_t*)in;
if(r && i<=--d) {
free((*root)[d-i]);
memmove(&(*root)[d-i],&(*root)[d-i+1],(d-i+1)*sizeof r);
return in;
}
} break;
case REMOVE: while( *(int*)dynarray(root,ts,GET,in,&d)>=0 )
dynarray(root,ts,REMOVEAT,&d,0);
}
return 0;
}
void outmy(Myp s)
{
printf("\n%s,%s,%d",s->name,s->city,s->salary);
}
main()
{
My z[]={{"Buffet","Omaha",INT_MAX},{"Jobs","Palo Alto",1},{"Madoff","NYC",INT_MIN}};
Str80 y[]={ "123","456","7890" };
char **ptr=0;
int x=1;
/* precondition for first use: ptr==NULL */
dynarray(&ptr,SPTR,ADD,"test1.txt",0);
dynarray(&ptr,SPTR,ADD,"test2.txt",0);
dynarray(&ptr,SPTR,ADD,"t3.txt",0);
dynarray(&ptr,SPTR,REMOVEAT,&x,0); /* remove at index/key ==1 */
dynarray(&ptr,SPTR,REMOVE,"test1.txt",0);
dynarray(&ptr,SPTR,GET,"t3.txt",&x);
dynarray(&ptr,SPTR,LOOP,puts,0);
/* another option for enumerating */
dynarray(&ptr,SPTR,COUNT,0,&x);
while( x-- )
puts(ptr[x]);
dynarray(&ptr,SPTR,FREE,0,0); /* frees all mallocs and set ptr to NULL */
/* start for another (user)type */
dynarray(&ptr,S80,ADD,y[0],0);
dynarray(&ptr,S80,ADD,y[1],0);
dynarray(&ptr,S80,ADD,y[2],0);
dynarray(&ptr,S80,ADD,y[0],0);
dynarray(&ptr,S80,LOOP,puts,0);
dynarray(&ptr,S80,FREE,0,0); /* frees all mallocs and set ptr to NULL */
/* start for another (user)struct-type */
dynarray(&ptr,MY,ADD,&z[0],0);
dynarray(&ptr,MY,ADD,&z[1],0);
dynarray(&ptr,MY,ADD,&z[2],0);
dynarray(&ptr,MY,ADD,&z[0],0);
dynarray(&ptr,MY,LOOP,outmy,0);
dynarray(&ptr,MY,FREE,0,0);
return 0;
}
There is sglib, which implements various lists,hashmaps and rbtrees in a generic fashion (i.e. by specializing over a type). There is also a fast sorting function for arrays:
http://sglib.sourceforge.net/
qLibc implements a vector in pure C. The data structure allows it to store any type of object like (void *object) and it provides convenient wrappers for string, formatted string and integer types.
Here's a sample code for your idea.
qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->addstr(vector, "Hello");
vector->addstrf(vector, "World %d", 123);
char *finalstring = vector->tostring(vector);
printf("%s", finalstring);
free(finalstring)
vector->free(vector);
for object type:
int a = 1, b = 2;
qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->add(vector, (void *)&a, sizeof(int));
vector->add(vector, (void *)&b, sizeof(int));
int *finalarray = vector->toarray(vector);
printf("a = %d, b = %d", finalarray[0], finalarray[1]);
free(finalarray)
vector->free(vector);
Note) I made this sample code just for your reference, copying from its example code.
it might have typo errors.
You can check out the Full API reference at http://wolkykim.github.io/qlibc/
I'm using the following macro implementation without problems so far. It isn't a complete implementation but grows the array automatically :
#define DECLARE_DYN_ARRAY(T) \
typedef struct \
{ \
T *buf; \
size_t n; \
size_t reserved; \
} T ## Array;
#define DYN_ARRAY(T) T ## Array
#define DYN_ADD(array, value, errorLabel) DYN_ADD_REALLOC(array, value, errorLabel, realloc)
#define DYN_ADD_REALLOC(array, value, errorLabel, realloc) \
{ \
if ((array).n >= (array).reserved) \
{ \
if (!(array).reserved) (array).reserved = 10; \
(array).reserved *= 2; \
void *ptr = realloc((array).buf, sizeof(*(array).buf)*(array).reserved); \
if (!ptr) goto errorLabel; \
(array).buf = ptr; \
} \
(array).buf[(array).n++] = value; \
}
To use you first write: DECLARE_DYN_ARRAY(YourType)
To declare variables you write DYN_ARRAY(YourType) array = {0}.
You add elements with DYN_ADD(array, element, errorLabel).
You access elements with array.buf[i].
You get the number of elements with array.n.
When done you free it with free(array.buf) (or whatever function you used to allocate it.)
I usually roll my own code for purposes such as this, like you did. It's not particularly difficult, but having type safety etc. is not easily achievable without a whole OO framework.
As mentioned before, glib offers what you need - if glib2 is too big for you, you could still go with glib1.2. It's quite old, but doesn't have external dependencies (except for pthread if you need thread support). The code can also be integrated into larger projects, if necessary. It's LGPL licensed.
Personally, I prefer "Gena" library. It closely resembles stl::vector in pure C89.
It is comfortable to use because you can:
Access vector elements just like plain C arrays: vec[k][j];
Have multi-dimentional arrays;
Copy vectors;
Instantiate necessary vector types once in a separate module, instead of doing this every time you needed a vector;
You can choose how to pass values into a vector and how to return them from it: by value or by pointer.
You can check it out here:
https://github.com/cher-nov/Gena

Resources