C structure multiple types - c

I'd like to write a library in C and I don't know what is the recommended way. I got for example structure and multiple functions like this:
typedef struct example
{
int *val;
struct example *next;
} Example;
and I have build function for multiple types of val
Example* build() { do sth };
Example* buildf() { do sth }; // val is float
Example* buildd() { do sth }; // val is double
What is the better practice (used in "professional" library). Use pointer to void and casting or have structure for all possibilities - int, float, double.

Use a union and some way to store type info:
typedef struct example
{
enum{ T_STRUCT_WITH_INT, T_STRUCT_WITH_FLOAT, T_SO_ON } type;
union {
int val_int;
float val_float;
} val;
struct example *next;
} Example;
Access fields after checking type by s->val.val_int
In C11 you can have union anonymous and fields can be accessed like s->val_int

This is primarily based on some combination of opinion, experience and the specific requirements at hand.
The following approach is possible, inspired by some container library work by Jacob Navia. I've never used it myself:
struct container_node {
struct container_node *link_here, *link_there, *link_elsewhere;
/*...*/
char data[0]; /* C90 style of "flexible array member" */
};
struct container_node *container_node_alloc(size_t data_size);
The allocation function allocates the node large enough so that data[0] through data[data_size-1] bytes of storage are available. Through another set of API functions, user data of arbitrary type be copied in and out.
The following approach is sometimes called "intrusive container". The container defines only a "base class" consisting of the link structure. The user must embed this structure into their own structure:
struct container_node {
struct container_node *next, *prev;
};
void container_insert(struct container *container, struct container_node *n);
struct container_node *container_first(struct container *container);
The user does this:
struct my_widget {
struct container_node container_links;
int widget_height;
/* ... */
};
/* .... */
/* We don't insert my_widget, but rather its links base. */
container_insert(&widg_container, &widget->container_links);
Some macros are used to convert between a pointer to the widget and a pointer to the container links. See the container_of macro used widely in the Linux kernel:
struct my_widget *wptr = container_of(container_first(&widg_container),
struct my_widget, container_links);
See this question.
Then there approaches of storing a union in each node, which provides an integer, floating-point-value or a pointer. In that case, the data is separately allocated (though not necessarily: if the caller controls the allocation of the nodes, it's still possible to put the node structure and the user data in a buffer that came from a single malloc call).
Finally, there are also approaches which wrap these techniques with preprocessor templating, an example of which are the BSD QUEUE macros.

Related

Opaque structure with flexible array member

Suppose I have a struct declaration in a header file like:
event.h
struct event_t;
and in the corresponding C file I would like to sort-of alias it with the Linux-specific struct inotify_event. The problem is that struct inotify_event contains flexible array member:
struct inotify_event {
int wd;
uint32_t mask;
uint32_t cookie;
uint32_t len;
char name[];
};
As per 6.7.2.1(p3) (emphasize mine):
A structure or union shall not contain a member with incomplete or
function type (hence, a structure shall not contain an instance of
itself, but may contain a pointer to an instance of itself), except
that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union
containing, possibly recursively, a member that is such a structure)
shall not be a member of a structure or an element of an array.
it is not possible to define the struct event_t as
struct event_t{
struct inotify_event base; //Non-conforming
};
So I could convert struct event_t * to struct inotify_event *. Since the 6.7.2.1(p3) concerns only about structs the solution I see is to redeclare the tag name as
union event_t
and then define it later as a single element union.
union event_t{
struct inotify_event event; //Conforming?
};
The only requirement the Standard imposes on union that I found is that the set of members of a union must be non-empty 6.2.5(p20) (emphasize mine):
A union type describes an overlapping nonempty set of member objects,
each of which has an optionally specified name and possibly distinct
type.
QUESTION: Is it a conforming/common way to hide an implementation details of some specific data structure through union?
This is how I would do it:
event.h
struct event_t;
event_t *create_event(void);
void free_event(event_t *ev);
event.c
#include "event.h";
event_t *create_event(void)
{
inotify_event *iev = ...;
return (event_t *)iev;
}
void free_event(event_t *ev)
{
inotify_event *iev = (inotify_event *)ev;
// free the event
}
However, if you want to store additional data with the event then:
event.h
struct event_t;
event_t *create_event(void);
void free_event(event_t *ev);
event.c
#include "event.h";
struct event_t
{
inotify_event *iev;
// additional data
};
event_t *create_event(void)
{
inotify_event *iev = ...;
event_t *ev = malloc(sizeof(event_t));
ev.iev = iev;
return ev;
}
void free_event(event_t *ev)
{
inotify_event *iev = (inotify_event *)ev.iev;
// free the event (iev) first
free(ev);
}
If you have multiple implementations that you need to hide in event_t then:
enum event_type
{
EVENT_TYPE_INOTIFY,
EVENT_TYPE_INOTIFY2,
};
struct event_t
{
event_type type;
union {
inotify_event *iev; // you use this when type == EVENT_TYPE_INOTIFY
inotify_event2 *iev2; // you use this when type == EVENT_TYPE_INOTIFY2
}
// additional data
};
By far the simplest technique is to put this into your event.h header:
typedef struct inotify_event event_t;
This declares that there is a structure type struct inotify_event and declares an alias for it event_t. But it does not define the content of struct inotify_event at all.
Only the implementation code in event.c includes the definition of struct inotify_event from the system header; everything else does not include that header and cannot access the elements of an event_t except through the accessor API you define.
You can enforce this separation of duties by code review β€” or by checking with grep, or other similar techniques β€” to ensure that no code except the implementation of your event type uses the system header for inotify_event. And, if you port to a system other than Linux without support for inotify, then you simply provide an alternative opaque structure type in place of struct inotify_event in your event.h header.
This avoids all questions about whether there are flexible array members within structures, etc; it is all a non-issue.
Note the Q&A about What does a type followed by _t (underscore t) represent? . Be cautious about creating your own types with the _t suffix ΒΈβ€” consider using a prefix on such type names that gives you a chance that your names will be distinct from those provided by the system.
Single element union makes no sense. The purpose of union is to serve as a kind of polymorphic struct. struct members are accessed by offset, this is why is impossible to put an incomplete struct or array in the middle of a struct.
For example
struct foo { int a; int b[]; int c; };
In this example is impossible for the compiler to determine the address of c because b size can vary at runtime. But if you put incomplete array at the end all struct members address can be determined by the address of the start of the struct. Keep in mind that pointers are just address, so you can have any pointers to any structs and all the offsets can be determined, but you will need to deal with extra alloc/free stuff.
When you create an union you telling to compiler Hey! I have this members, reserve enough space for me so that I can treat this variable as foo or bar. In another words, the compiler will take the largest union member and this will be the size of the union. A common use for union is for representing multiple kinds of values.
typedef union { int integer, float real, char *string } value_type;
This way you can treat value_type as int, float, or a char pointer. You're code need to know the how to treat each member but the compiler will make sure that when you do malloc(sizeof value_type) you have enough space for the tree types.
Now your problem. You want to hide implementation details. Usually this is done by declaring a type or struct incompletely in a header, and completely only on your object files. Because of this when the user include your header all the information that the compiler has is struct my_struct;. It can't tell the size of my_struct so is impossible for you to allocate it as malloc(sizeof struct my_struct). Also since the user hasn't the member definitions it can't mess up with the struct internals.
Working like this you will need to provide user with functions for allocating and freeing my_struct, for example struct my_struct *foo = my_struct_new() and my_struct_destroy(foo).
You're already doing this. To deal with the struct inotify problem I would do one of these.
(1) Surround OS specific with #ifdef for that OS, so that the event_t has only the right members defined depending on the operating system. You will need #ifdef on your functions. This has the advantage to keep useless code out of final binary, so smaller footprint.
(2) Have pointers to OS specific structs and let runtime decide what to do. This easier to maintain.

Why does "struct T* next" compile when T isn't an existing type?

I am using MinGW on Windows. I am building linked list and I am confused with this.
#include <stdio.h>
#include <stdlib.h>
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
int main(void)
{
List item;
List * head;
head = NULL;
return 0;
}
I now that struct can't have struct variable(object, instance of that struct), but can have pointer of that struct type. Didn't know that pointer can be pointer of unexisting type. struct BlaBla * next;(not for linked list, it must be struct Data * next but mean general talking)
Yes, you can, because then the compiler, upon encountering the unknown type name for the first time, assumes that there's somehwere a struct type definition with this name. Then it will forward-declare the struct name for you, let you use it as a pointer, but you can't dereference it nor can you do pointer arithmetic on it (since it's an incomplete type).
The compiler will accept code such as your example:
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
This is okay because the size of pointers is known to the compiler, and the compiler is assuming that the struct will be defined before it is dereferenced.
Because the compiler acts this way, it's possible to do this:
typedef struct Data
{
int x;
int y;
struct Data * next; /* points to itself */
} List;
However, if you were to include the struct inline, like this:
typedef struct Data
{
int x;
int y;
struct BlaBla blaStruct; /* Not a pointer. Won't compile. */
}List;
The compiler can't work out how big struct Data is because it doesn't know how big struct BlaBla is. To get this to compile, you need to include the definition of struct BlaBla.
Note that, as soon as you need to access the members of struct BlaBla, you will need to include the header file that defines it.
It depends on what you mean by "unexisting". If you haven't even declared BlaBla, you'll get an error.
If you've declared it but not yet defined it, that will work fine. You're allowed to have pointers to incomplete types.
In fact, that's the normal way of doing opaque pointers in C.
So, you might think that this is invalid because there's no declaration of struct BlaBla in scope:
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
However, it's actually okay since it's both declaring struct BlaBla and defining next at the same time.
Of course, since definition implies declaration, this is also okay:
struct BlaBla { int xyzzy; };
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
In order to declare a variable or field of a given type, pass one as a parameter, or copy one to another of the same type, the compiler has to know how many bytes the variable or field occupies, what alignment requirements it has (if any), and what other pointer types it's compatible with, but that's all the compiler needs to know about it. In all common dialects of C, a pointer to any structure will always be the same size and require the same alignment, regardless of the size of the structure to which it points or what that structure may contain, and pointers to any structure type are only compatible with other pointers to the same structure type.
Consequently, code which doesn't need to do anything with pointers to a structure except allocate space to hold the pointers themselves [as opposed to the structures at which they point], pass them as parameters, or copy them to other pointers, doesn't need to know anything about the structure type to which they point beyond its unique name. Code which needs to allocate space for a structure (as opposed to a pointer to one) or access any of its members must know more about its type, but code which doesn't do those things doesn't need such information.

Is this a coding convention?

I am doing feature enhancement on a piece of code, and here is what i saw in existing code. If there is a enum or struct declared, later there is always a typedef:
enum _Mode {
MODE1 = 0,
MODE2,
MODE3
};
typedef enum _Mode Mode;
Similary for structure:
struct _Slot {
void * mem1;
int mem2;
};
typedef struct _Slot Slot;
Can't the structures be directly declared as in enum? Why there is a typedef for something as minor as underscore? Is this a coding convention?
Kindly give good answers, because i need to add some code, and if this is a rule, i need to follow it.
Please help.
P.S: As an additional info, the source code is written in C, and Linux is the platform.
In C, to declare a varaible with a struct type you would have to use the following:
struct _Slot a;
The typedef allows you to make this look somewhat neater by essentially creating an alias. And allowing variable declaration like so:
Slot a;
In C there are separate "namespaces" for struct and typedef. Thus, without a typedef you would have to access Slot as struct _Slot, which is more typing. Compare:
struct Slot { ... };
struct Slot s;
struct Slot create_s() { ... }
void use_s(struct Slot s) { ... }
vs
typedef struct _Slot { ... } Slot;
Slot s;
Slot create_s() { ... }
void use_s(Slot s) { ... }
Also see http://en.wikipedia.org/wiki/Struct_(C_programming_language)#typedef for details, like possible namespace clash.
If the following is a structure:
struct _Slot {
void * mem1;
int mem2;
};
you need the following to declare a variable:
struct _Slot s;
Notice the extra struct before _Slot. It seems more natural to declare a variable like Slot s, isn't it?
If you want to get rid of extra struct, you need a typedef:
typedef struct _Slot Slot;
Slot s;
It's sort of code obfuscation technique which only make sense in small amount of cases.
People say it's more natural to not write "struct" and other subjective things.
But objectively, one at least a) can't forward declare such typedeffed struct, b) have to jump through one hoop when using ctags.

C Variable Member List for structs, is this possible?

I have a question about structures having a "variable members list" similar to the "variable argument list" that we can define functions as having.
I may sound stupid or completely off the line in terms of C language basics, but please correct me if I am wrong.
So can I have a C struct like this:
struct Var_Members_Interface
{
int intMember;
char *charMember;
... // is this possible?
};
My idea is to have a c style interface that can be implemented by the classes but these classes can have additional members in this structure. However, they must have intMember and charMember.
Thanks in advance.
The closest approximation in C99 (but not C89) is to have a flexible array member at the end of the structure:
struct Var_Members_Interface
{
int intMember;
char *charMember;
Type flexArrayMember[];
};
You can now dynamically allocate the structure with an array of the type Type at the end, and access the array:
struct Var_Members_Interface *vmi = malloc(sizeof(*vmi) + N * sizeof(Type));
vmi->flexArrayMember[i] = ...;
Note that this cannot be used in C++.
But that isn't a very close approximation to what you are after. What you are after cannot be done in C with a single structure type, and can only be approximated in C++ via inheritance - see other answers.
One trick that you can get away with - usually - in C uses multiple structure types and lots of casts:
struct VM_Base
{
int intMember;
char *charMember;
};
struct VM_Variant1
{
int intMember;
char *charMember;
int intArray[3];
};
struct VM_Variant2
{
int intMember;
char *charMember;
Type typeMember;
};
struct VM_Variant3
{
int intMember;
char *charMember;
double doubleMember;
};
Now, with some sledgehammering casts, you can write functions which take 'struct VM_Base *' arguments, and pass in a pointer to any of the VM_VariantN types. The 'intMember' can probably be used to tell which of the variants you actually have. This is more or less what happens with the POSIX sockets functions. There are different types of socket address, and the structures have different lengths, but they have a common prefix, and the correct code ends up being called because the common prefix identifies the type of socket address. (The design is not elegant; but it was standard - a de facto standard from BSD sockets - before POSIX standardized it. And the BSD design pre-dates C89, let alone C99. Were it being designed now, from scratch, with no requirement for compatibility with existing code, it would be done differently.)
This technique is ugly as sin and requires casts galore to make it compile -- and great care to make it work correctly. You shouldn't bother with this sort of mess in C++.
You can't do anything like this with direct language support in C; but in C++, classes that extended your struct would inherit those data members and could add their own. So in C++, not only can you do this, but it's a normal mode of operation.
You first need to understand what a struct really is.
A struct in C is little more than a standard for interpreting bytes in memory.
To see what that means, let's use your struct:
struct Var_Members_Interface
{
int intMember;
char *charMember;
};
struct Var_Members_Interface instance; //An instance of the struct
What this means is, "I'll reserve some memory and call it instance, and I'll interpret the first few bytes to mean an integer, and the next few bytes to mean that the point to somewhere in memory."
Given this, it makes little sense to have "variable-member" structs, because a struct is just the layout specification for an existing block of memory -- and existing blocks don't have "variable" length.
You could do it the way the old X11 Xt widget library did it:
struct Var_Members_Interface {
int intMember;
char *charMember;
};
struct Other_Part {
int extraInt;
char *extraString;
}
struct Var_Other_Interface {
struct Var_Members_Interface base;
struct Other_Part other;
};
As long as you're careful with your allocations, alignment, and padding issues, then this will work:
struct Var_Other_Interface *other = create_other();
struct Var_Members_Interface *member = (struct Var_Other_Interface *)other;
struct Var_Other_Interface *back_again = (struct Var_Other_Interface)member;
And you can nest the structs as deep as needed to get a single inheritance hierarchy.
This sort of thing is not for the feint of heart: you have to be very careful with you allocations, structure nesting, etc.
Have a look at an old school Xt widget and you'll get the idea; Xt widgets were usually implemented in three files: a C source file, a public header with the function interface, and a private header to define the structure layout (this one would be needed for subclassing).
For example, the Ghostscript widget that I used to use in mgv looked like this:
typedef struct {
/* Bunch of stuff. */
} GhostviewPart;
typedef struct _GhostviewRec {
CorePart core;
GhostviewPart ghostview;
} GhostviewRec;
The CorePart was the standard Xt widget definition and the GhostviewRec was the actual widget itself.
Not exactly what you are looking for but you can create a void pointer within your struct that can be used to point to another struct where the new types are defined.
struct Var_Members_Interface
{
int intMember;
char *charMember;
void *otherMembers;
};
Edit: The solution in this article might be a lot closer to what you are looking for.
You have two choices I think. You can emulate what C++ does but unfortunately, you have to see all the gory details. You define your common base struct and have that as a member of all your variant structs e.g.
struct VM_Base
{
int intMember;
char *charMember;
};
struct VM_Variant1
{
struct VM_Base base;
int foo;
};
struct VM_Variant2
{
struct VM_Base base;
char *charMember;
double bar;
};
struct VM_Variant3
{
struct VM_Base base;
char *charMember;
char baz[10];
};
Pointers to any of the variant structs are also pointers to the base member of the variant struct so you can cast to the base member freely. Going back the other way is obviously more problematic, since you need a check to make sure you are casting to the right type.
You can do away with the casts by using union instead e.g.
struct VM_Variant1
{
struct VM_Base base;
int foo;
};
struct VM_Variant2
{
struct VM_Base base;
char *charMember;
double bar;
};
struct VM_Variant3
{
struct VM_Base base;
char *charMember;
char baz[10];
};
struct VM
{
int intMember;
char *charMember;
union
{
struct VM_Variant1 vm1;
struct VM_Variant2 vm2;
struct VM_Variant3 vm3;
}
};
This second method obviates the need for type casts. You access the members like this:
double aDouble = aVMStruct.vm2.bar;
The three members of the union overlay each other in memory so the allocated block will only be the size of the largest of the three variants.

Modular data structure in C with dynamic data type

For my upcoming university C project, I'm requested to have modular code as C allows it. Basically, I'll have .c file and a corresponding .h file for some data structure, like a linked list, binary tree, hash table, whatever...
Using a linked list as an example, I have this:
typedef struct sLinkedList {
int value;
struct sLinkedList *next;
} List;
But this forces value to be of type int and the user using this linked list library would be forced to directly change the source code of the library. I want to avoid that, I want to avoid the need to change the library, to make the code as modular as possible.
My project may need to use a linked list for a list of integers, or maybe a list of some structure. But I'm not going to duplicate the library files/code and change the code accordingly.
How can I solve this?
Unfortunately, there is no simple way to solve this. The most common, pure C approach to this type of situation is to use a void*, and to copy the value into memory allocated by you into the pointer. This makes usage tricky, though, and is very error prone.
Another alternative no one has mentioned yet can be found in the Linux kernel's list.h generic linked list implementation. The principle is this:
/* generic definition */
struct list {
strict list *next, *prev;
};
// some more code
/* specific version */
struct intlist {
struct list list;
int i;
};
If you make struct intlist* pointers, they can safely be cast (in C) to struct list* pointers, thus allowing you to write genericized functions that operate on struct list* and have them work regardless of datatype.
The list.h implementation uses some macro trickery to support arbitrary placement of the struct list inside your specific list, but I prefer to rely on the struct-cast-to-first-member trick myself. It makes the calling code much easier to read. Granted, it disables "multiple inheritance" (assuming you consider this to be some kind of inheritance) but next(mylist) looks nicer than next(mylist, list). Plus, if you can avoid delving into offsetof hackery, you're probably going to end up in better shape.
Since this is a university project, we can't just give you the answer. Instead, I'd invite you to meditate on two C features: the void pointer (which you've likely encountered before), and the token pasting operator (which you may not have).
You can avoid this by defining value as void* value;. You can assign a pointer to any type of data this way, but the calling code is required to cast and dereference the pointer to the correct type. One way to keep track of this would be to add a short char array to the struct to note the type name.
This problem is precisely the reason why templates were developed for C++. The approach I've used once or twice in C is to have the value field be a void*, and cast the values thereto on insertion and cast them back on retrieval. This is far from type-safe, of course. For extra modularity, I might write insert_int(), get_mystruct() etc. functions for each type you use this for, and do the casting there.
You can use Void* instead of int. This allows the data to be of any type. But the user should be aware of the type of data.
For that, optionally you can have another member which represents Type. which is of enum {INT,CHAR,float...}
Unlike C++ where one can use template, void * is the de-facto C solution.
Also, you can put the elements of the linked list in a separate struct, e.g:
typedef struct sLinkedListElem {
int value; /* or "void * value" */
} ListElem;
typedef struct sLinkedList {
ListElem data;
struct sLinkedList *next;
} List;
so that the elements can be changed without affecting the link-ing code.
Here is an example of linked list utilities in C:
struct Single_List_Node
{
struct Single_List * p_next;
void * p_data;
};
struct Double_List_Node
{
struct Double_List * p_next;
struct Double_List * p_prev; // pointer to previous node
void * p_data;
};
struct Single_List_Data_Type
{
size_t size; // Number of elements in list
struct Single_List_Node * p_first_node;
struct Single_List_Node * p_last_node; // To make appending faster.
};
Some generic functions:
void Single_List_Create(struct Single_List_Data_Type * p_list)
{
if (p_list)
{
p_list->size = 0;
p_list->first_node = 0;
p_list->last_node = p_list->first_node;
}
return;
}
void Single_List_Append(struct Single_List_Data_Type * p_list,
void * p_data)
{
if (p_list)
{
struct Single_List_Node * p_new_node = malloc(sizeof(struct Single_List_Node));
if (p_new_node)
{
p_new_node->p_data = p_data;
p_new_node->p_next = 0;
if (p_list->last_node)
{
p_list->last_node->p_next = p_new_node;
}
else
{
if (p_list->first_node == 0)
{
p_list->first_node = p_new_node;
p_list->last_node = p_new_node;
}
else
{
struct Single_List_Node * p_last_node = 0;
p_last_node = p_list->first_node;
while (p_last_node->p_next)
{
p_last_node = p_last_node->p_next;
}
p_list->last_node->p_next = p_new_node;
p_list->last_node = p_new_node;
}
}
++(p_list->size);
}
}
return;
}
You can put all these functions into a single source file and the function declarations into a header file. This will allow you to use the functions with other programs and not have to recompile all the time. The void * for the pointer to data will allow you to use the list with many different data types.
(The above code comes as-is and has not been tested with any compiler. The responsibility of bug fixing is up to the user of the examples.)

Resources