I'm trying to make a type-safe generic linked list in C using macros. It should work similarly to how templates work in C++. For example,
LIST(int) *list = LIST_CREATE(int);
My first attempt was for #define LIST(TYPE) (the macro I used above) to define a struct _List_##TYPE {...}. That, however, did not work because the struct would be redefined every time I declared a new list. I remedied the problem by doing this:
/* You would first have to use this macro, which will define
the `struct _List_##TYPE`... */
DEFINE_LIST(int);
int main(void)
{
/* ... And this macro would just be an alias for the struct, it
wouldn't actually define it. */
LIST(int) *list = LIST_CREATE(int);
return 0;
}
/* This is how the macros look like */
#define DEFINE_LIST(TYPE) \
struct _List_##TYPE \
{ \
... \
}
#define LIST(TYPE) \
struct _List_##TYPE
But another problem is that when I have multiple files that use DEFINE_LIST(int), for example, and some of them include each other, then there will still be multiple definitions of the same struct. Is there any way to make DEFINE_LIST check if the struct has already been defined?
/* one.h */
DEFINE_LIST(int);
/* two.h */
#include "one.h"
DEFINE_LIST(int); /* Error: already defined in one.h */
I tackled this problem in C before C++ acquired templates and I still
have code.
You can't define a truly generic typesafe container-of-T template with macros
in a way that's confined entirely to header files. The standard preprocessor
provides no means of "pushing" and "popping" the macro assignments you will
require so as preserve their integrity through nested and sequential
contexts of expansion. And you will encounter nested contexts as soon as you
try to eat your own dog food by defining a container-of-containers-of-T.
The thing can be done, as we'll see, but as #immortal suggests, it entails
generating distinct .h and .c files for each value of T that you require.
You can, for example, define a completely generic list-of-T with macros in
an inline file, say, list_type.inl, and then include list_type.inl in a
each of pair of small set-up wrappers - list_float.h and list_float.c - that
will respectively define and implement the list-of-float container. Similarly
for list-of-int, list-of-list-of-float, list-of-vector-of-list-of-double,
and so so.
A schematic example will make all clear. But first just get the full measure of
the eat-your-own-dogfood challenge.
Consider such a second-order container as a list-of-lists-of-thingummy. We want to
be able to instantiate these by setting T = list-of-thingummy for our macro
list-of-T solution. But in no way is list-of-thingummy going to be a POD
datatype. Whether list-of-thingummy is our own dogfood or somebody else's, it's
going to be an abstract datatype that lives on the heap and is represented to
its users through a typedef-ed pointer type. Or at the very least, it is going
to have dynamic components held on the heap. In any case, not POD.
This means it's not enough for our list-of-T solution just to be told that
T = list-of-thingummy. It must also be told whether a T requires non-POD
copy-construction and destruction, and if so how to copy-construct and destroy
one. In C terms, that means:
Copy-construction: How to create a copy of a given T in a T-sized
region of uncommitted memory, given the address of such a region.
Destruction: How to destroy the T at a given address.
We can do without knowing about default construction or construction from
non-T parameters, as we can reasonably restrict our list-of-T solution to
the containment of objects copied from user-supplied originals. But we do
have to copy them, and we have to dispose of our copies.
Next, suppose that we aspire to offer a template for set-of-T, or map-of-T1-to-T2,
in addition to list-of-T. These key-ordered datatypes add another parameter
we will have to plug in for any non-POD value of T or T1, namely how to order
any two objects of the key type. Indeed we will need that parameter for
any key datatype for which memcmp() won't do.
Having noted that, we'll stick with the simpler list-of-T problem for the
schematic example; and for further simplicity I'll forget the desirability
of any const API.
For this and any other template container type we'll want some token-pasting
macros that let us conveniently assemble identifiers of functions and types,
plus probably other utility macros. These can all go in a header, say macro_kit.h,
such as:
#ifndef MACRO_KIT_H
#define MACRO_KIT_H
/* macro_kit.h */
#define _CAT2(x,y) x##y
// Concatenate 2 tokens x and y
#define CAT2(x,y) _CAT2(x,y)
// Concatenate 3 tokens x, y and z
#define CAT3(x,y,z) CAT2(x,CAT2(y,z))
// Join 2 tokens x and y with '_' = x_y
#define JOIN2(x,y) CAT3(x,_,y)
// Join 3 tokens x, y and z with '_' = x_y_z
#define JOIN3(x,y,z) JOIN2(x,JOIN2(y,z))
// Compute the memory footprint of n T's
#define SPAN(n,T) ((n) * sizeof(T))
#endif
Now to the schematic structure of list_type.inl:
//! There is intentionally no idempotence guard on this file
#include "macro_kit.h"
#include <stddef.h>
#ifndef INCLUDE_LIST_TYPE_INL
#error This file should only be included from headers \
that define INCLUDE_LIST_TYPE_INL
#endif
#ifndef LIST_ELEMENT_TYPE
#error Need a definition for LIST_ELEMENT_TYPE
#endif
/* list_type.inl
Defines and implements a generic list-of-T container
for T the current values of the macros:
- LIST_ELEMENT_TYPE:
- must have a definition = the datatype (or typedef alias) for \
which a list container is required.
- LIST_ELEMENT_COPY_INITOR:
- If undefined, then LIST_ELEMENT_TYPE is assumed to be copy-
initializable by the assignment operator. Otherwise must be defined
as the name of a copy initialization function having a prototype of
the form:
LIST_ELEMENT_TYPE * copy_initor_name(LIST_ELEMENT_TYPE *pdest,
LIST_ELEMENT_TYPE *psrc);
that will attempt to copy the LIST_ELEMENT_TYPE at `psrc` into the
uncommitted memory at `pdest`, returning `pdest` on success and NULL
on failure.
N.B. This file itself defines the copy initializor for the list-type
that it generates.
- LIST_ELEMENT_DISPOSE
If undefined, then LIST_ELEMENT_TYPE is assumed to need no
destruction. Otherwise the name of a destructor function having a
protoype of the form:
void dtor_name(LIST_ELEMENT_TYPE pt*);
that appropriately destroys the LIST_ELEMENT_TYPE at `pt`.
N.B. This file itself defines the destructor for the list-type that
it generates.
*/
/* Define the names of the list-type to generate,
e.g. list_int, list_float
*/
#define LIST_TYPE JOIN2(list,LIST_ELEMENT_TYPE)
/* Define the function-names of the LIST_TYPE API.
Each of the API macros LIST_XXXX generates a function name in
which LIST becomes the value of LIST_TYPE and XXXX becomes lowercase,
e.g list_int_new
*/
#define LIST_NEW JOIN2(LIST_TYPE,new)
#define LIST_NODE JOIN2(LIST_TYPE,node)
#define LIST_DISPOSE JOIN2(LIST_TYPE,dispose)
#define LIST_COPY_INIT JOIN2(LIST_TYPE,copy_init)
#define LIST_COPY JOIN2(LIST_TYPE,copy)
#define LIST_BEGIN JOIN2(LIST_TYPE,begin)
#define LIST_END JOIN2(LIST_TYPE,end)
#define LIST_SIZE JOIN2(LIST_TYPE,size)
#define LIST_INSERT_BEFORE JOIN3(LIST_TYPE,insert,before)
#define LIST_DELETE_BEFORE JOIN3(LIST_TYPE,delete,before)
#define LIST_PUSH_BACK JOIN3(LIST_TYPE,push,back)
#define LIST_PUSH_FRONT JOIN3(LIST_TYPE,push,front)
#define LIST_POP_BACK JOIN3(LIST_TYPE,pop,back)
#define LIST_POP_FRONT JOIN3(LIST_TYPE,pop,front)
#define LIST_NODE_GET JOIN2(LIST_NODE,get)
#define LIST_NODE_NEXT JOIN2(LIST_NODE,next)
#define LIST_NODE_PREV JOIN2(LIST_NODE,prev)
/* Define the name of the structure used to implement a LIST_TYPE.
This structure is not exposed to user code.
*/
#define LIST_STRUCT JOIN2(LIST_TYPE,struct)
/* Define the name of the structure used to implement a node of a LIST_TYPE.
This structure is not exposed to user code.
*/
#define LIST_NODE_STRUCT JOIN2(LIST_NODE,struct)
/* The LIST_TYPE API... */
// Define the abstract list type
typedef struct LIST_STRUCT * LIST_TYPE;
// Define the abstract list node type
typedef struct LIST_NODE_STRUCT * LIST_NODE;
/* Return a pointer to the LIST_ELEMENT_TYPE in a LIST_NODE `node`,
or NULL if `node` is null
*/
extern LIST_ELEMENT_TYPE * LIST_NODE_GET(LIST_NODE node);
/* Return the LIST_NODE successor of a LIST_NODE `node`,
or NULL if `node` is null.
*/
extern LIST_NODE LIST_NODE_NEXT(LIST_NODE node);
/* Return the LIST_NODE predecessor of a LIST_NODE `node`,
or NULL if `node` is null.
*/
extern LIST_NODE LIST_NODE_PREV(LIST_NODE node);
/* Create a new LIST_TYPE optionally initialized with elements copied from
`start` and until `end`.
If `end` is null it is assumed == `start` + 1.
If `start` is not NULL then elements will be appended to the
LIST_TYPE until `end` or until an element cannot be successfully copied.
The size of the LIST_TYPE will be the number of successfully copied
elements.
*/
extern LIST_TYPE LIST_NEW(LIST_ELEMENT_TYPE *start, LIST_ELEMENT_TYPE *end);
/* Dispose of a LIST_TYPE
If the pointer to LIST_TYPE `plist` is not null and addresses
a non-null LIST_TYPE then the LIST_TYPE it addresses is
destroyed and set NULL.
*/
extern void LIST_DISPOSE(LIST_TYPE * plist);
/* Copy the LIST_TYPE at `psrc` into the LIST_TYPE-sized region at `pdest`,
returning `pdest` on success, else NULL.
If copying is unsuccessful the LIST_TYPE-sized region at `pdest is
unchanged.
*/
extern LIST_TYPE * LIST_COPY_INIT(LIST_TYPE *pdest, LIST_TYPE *psrc);
/* Return a copy of the LIST_TYPE `src`, or NULL if `src` cannot be
successfully copied.
*/
extern LIST_TYPE LIST_COPY(LIST_TYPE src);
/* Return a LIST_NODE referring to the start of the
LIST_TYPE `list`, or NULL if `list` is null.
*/
extern LIST_NODE LIST_BEGIN(LIST_TYPE list);
/* Return a LIST_NODE referring to the end of the
LIST_TYPE `list`, or NULL if `list` is null.
*/
extern LIST_NODE LIST_END(LIST_TYPE list);
/* Return the number of LIST_ELEMENT_TYPEs in the LIST_TYPE `list`
or 0 if `list` is null.
*/
extern size_t LIST_SIZE(LIST_TYPE list);
/* Etc. etc. - extern prototypes for all API functions.
...
...
*/
/* If LIST_IMPLEMENT is defined then the implementation of LIST_TYPE is
compiled, otherwise skipped. #define LIST_IMPLEMENT to include this
file in the .c file that implements LIST_TYPE. Leave it undefined
to include this file in the .h file that defines the LIST_TYPE API.
*/
#ifdef LIST_IMPLEMENT
// Implementation code now included.
// Standard library #includes...?
// The heap structure of a list node
struct LIST_NODE_STRUCT {
struct LIST_NODE_STRUCT * _next;
struct LIST_NODE_STRUCT * _prev;
LIST_ELEMENT_TYPE _data[1];
};
// The heap structure of a LIST_TYPE
struct LIST_STRUCT {
size_t _size;
struct LIST_NODE_STRUCT * _anchor;
};
/* Etc. etc. - implementations for all API functions
...
...
*/
/* Undefine LIST_IMPLEMENT whenever it was defined.
Should never fall through.
*/
#undef LIST_IMPLEMENT
#endif // LIST_IMPLEMENT
/* Always undefine all the LIST_TYPE parameters.
Should never fall through.
*/
#undef LIST_ELEMENT_TYPE
#undef LIST_ELEMENT_COPY_INITOR
#undef LIST_ELEMENT_DISPOSE
/* Also undefine the "I really meant to include this" flag. */
#undef INCLUDE_LIST_TYPE_INL
Note that list_type.inl has no macro-guard against mutliple inclusion. You want
at least some of it - at least the template API - to be included every time it is
seen.
If you read the comments at the top of the file you can guess how you would code
a wrapping header to import a list-of-int container type.
#ifndef LIST_INT_H
#define LIST_INT_H
/* list_int.h*/
#define LIST_ELEMENT_TYPE int
#define INCLUDE_LIST_TYPE_INL
#include "list_type.inl"
#endif
and likewise how you would code the wrapping header to import a list-of-list-of-int
container type:
#ifndef LIST_LIST_INT_H
#define LIST_LIST_INT_H
/* list_list_int.h*/
#define LIST_ELEMENT_TYPE list_int
#define LIST_ELEMENT_COPY_INIT list_int_copy_init
#define LIST_ELEMENT_DISPOSE list_int_dispose
#define INCLUDE_LIST_TYPE_INL
#include "list_type.inl"
#endif
Your applications can safely include such wrappers, e.g.
#include "list_int.h"
#include "list_list_int.h"
despite the fact the they define LIST_ELEMENT_TYPE in conflicting ways because
list_type.inl always #undefs all the macros that parameterize the list-type
when it's done with them: see the last few lines of the file.
Note too the use of the macro LIST_IMPLEMENT. If its undefined when list_type.inl
is parsed then only the template API is exposed; the template implementation is
skipped. If LIST_IMPLEMENT is defined then the whole file is compiled. Thus our
wrapping headers, by not defining LIST_IMPLEMENT, import only the list-type
API.
Conversely for our wrapping source files list_int.c, list_list_int.c, we will
define LIST_IMPLEMENT. After that, there's nothing to do but include the
corresponding header:
/* list_int.c */
#define LIST_IMPLEMENT
#include "list_int.h"
and:
/* list_list_int.c*/
#include "list_int.h"
#define LIST_IMPLEMENT
#include "list_list_int.h"
Now in your application, no list-template macros appear. Your wrapping
headers parse out to "real code":
#include "list_int.h"
#include "list_list_int.h"
// etc.
int main(void)
{
int idata[10] = {1,2,3,4,5,6,7,8,9,10};
//...
list_int lint = list_int_new(idata,idata + 10);
//...
list_list_int llint = list_list_int_new(&lint,0);
//...
list_int_dispose(&lint);
//...
list_list_int_dispose(&llint);
//...
exit(0);
}
To equip yourself with a "C template library" this way the only (!) hard work
is to write the .inl file for each container type you want and to test it
very, very thoroughly. You would then probably generate an object file
and header for each combination of native datatype and container type for
off-the-shelf linkage, and knock out the .h and .c wrappers in a jiffy for
other types on demand.
Needless to say, as soon as C++ sprouted templates my enthusiam for sweating
them out this way evaporated. But it can be done this way, completely
generically, if for some reason C is the only option.
You could always add a second argument to the DEFINE_LIST macro that will allow you to "name" the list. For instance:
#define DEFINE_LIST(TYPE, NAME) \
struct _List_##TYPE_##NAME \
{ \
TYPE member_1; \
struct _List_##TYPE_##NAME* next; \
}
Then you could simply do:
DEFINE_LIST(int, my_list);
//... more code that uses the "my_list" type
You would just have to restrict yourself to not re-using the same list "name" when two different header files include each other, and both use the DEFINE_LIST macro. You would also have to refer to the list by name when using LIST_CREATE, etc.
When passing the lists to functions that you've written, you can always create "generic" types that the user-defined "named" versions are cast to. This shouldn't affect anything since the actual information in the struct stays the same, and the "name" tag merely differentiates the types from a declaration rather than binary standpoint. For example, here is a function that takes list objects that store int types:
#define GENERIC_LIST_PTR(TYPE) struct _generic_list_type_##TYPE*
#define LIST_CAST_PTR(OBJ, TYPE) (GENERIC_LIST_PTR(TYPE))(OBJ)
void function(GENERIC_LIST_PTR(INT) list)
{
//...use list as normal (i.e., access it's int data-member, etc.)
}
DEFINE_LIST(int, my_list);
int main()
{
LIST(int, my_list)* list = LIST_CREATE(int, my_list);
function(LIST_CAST_PTR(list, int));
//...more code
return 0;
}
I know this isn't necessarily the most convenient thing, but this does resolve the naming issues, and you can control what versions of struct _generic_list_type_XXX are created in some private header file that other users won't be adding to (unless they wish to-do so for their own types) ... but it would be a mechanism for separating the declaration and the definition of the generic list-type from the actual user-defined list-type.
Why don't you use a library?
I like to use GLib but I hate the void pointers in my code, in order to get a typesafe version of the data types provided by GLib I coded some very simple macros:
http://pastebin.com/Pc0KsadV
If I want a list of Symbol* (assuming it's a type I defined earlier) I just need to to:
GLIST_INSTANCE(SymbolList, Symbol*, symbol_list);
If you don't want to use a whole library (which would be a kind of overkill) for a simple linked list, implement a list that handles void* and create some functions to encapsulate and make the correct type casting.
How about creating a list_template.h file and then creating a list_TYPE.h file and a list_TYPE.c file for every instance of the template. These can come with the proper header protectors, of course.
You can then only include your template header but make sure to add all the .c files to the compile and link process, and it should work.
This is basically what C++ does automatically for you... Duplicating the instances...
I really doubt you can do checking existence and defining (a struct) in one macro. Put another #ifndef check before DEFINE_LIST(int). It's not elegant but does what you want.
It is possible to create generic and type-safe containers with macros. From the viewpoint of the theory of computation, the language (code) generated from macro expansions can be recognized by a nondeterministic pushdown automata which means that it is at most a context-free grammar. The aforementioned statement makes our goal seems impossible to achieve since the container and its affiliated iterators should remember the type they contains, but this can only be done by a context-sensitive grammar. However, we can do some tricks!
The key to success lies in the compilation process, building symbol tables. If the type of variable can be recognized when compiler queries the table and no unsafe type casting occurs, then it is regarded as type-safe. Therefore, we have to give every struct a special name because struct name may conflict if two or more structs are declared on the same level of scope. The easiest way is to append the current line number to the struct name. The standard C supports predefined macro __LINE__ and macro concatenation / stringification since ANSI C (C89/C90).
Then, what we have to do is to hide some attributes into the struct we defined as above. If you want to create another list record at run-time, put a pointer to itself in the struct will actually solve the problem. However, this is not enough. We might need an extra variable to store how many list records we allocate at run-time. This helps us figure out how to free the memory when the list is destroy explicitly by programmers. Also, we can take the advantage of __typeof__() extension which is widely used in macro programming.
I am the author of the OpenGC3 which aims at building type-safe generic containers with macros, and here is a short and brief example of how this library works:
ccxll(int) list; // declare a list of type int
ccxll_init(list); // initialize the list record
for (int cnt = 8; cnt-- > 0; ) //
ccxll_push_back(list, rand()); // insert "rand()" to the end
ccxll_sort(list); // sort with comparator: XLEQ
CCXLL_INCR_AUTO(pnum, list) // traverse the list forward:
printf("num = %d\n", *pnum); // access elems through iters
ccxll_free(list); // destroy the list after use
It is quite similar to the syntax of the STL. The type of list is determined when list is declared. We have no need to concern about the type safety because there is no unsafe type casting when operations are performed to the list.
Related
I'm trying to achieve method overloading in C, preferably using macros so the header/library can handle the definitions and declarations instead of putting that onto the user. Now I've read this answer about using _Generic however the problem is my functions have struct types. So there's no way to evaluate their type using a __typeof__ of _Generic. I wonder if there is any way at all.
This is how my header file looks like (which is all we should be concerned with)-
#pragma once
// Macros for generic like use of the data structure
// Macros for the stack type itself
/*
* Define stack with corresponding type
* Converts Stack(int) to intstack_t
*/
#define Stack(type) type stack_t
// Macros for functions
/*
* Define createStack function
* Converts createStack(int, 5) to create_intstack(5)
*/
#define createStack(type, capacity) create_ ##type ##stack(capacity)
/*
* Define destroyStack function
* Converts destroyStack(someIntStack) to destroy_intstack(someIntStack)
* Where someIntStack is a pointer to a variable of type intstack_t
*/
#define destroyStack(stack) _Generic(stack, intstack_t*: destroy_intstack, charstack_t*: destroy_charstack)(stack)
/*
* Define push function
* Converts push(someIntStack, data) to intstack_push(someIntStack, data)
* Where someIntStack is a pointer to a variable of type intstack_t
*/
#define push(stack, data) _Generic(stack, intstack_t*: intstack_push, charstack_t*: charstack_push)(stack, data)
// Stack structure definition(s)
// int stack definition
typedef struct IntegerStack {
int top;
unsigned capacity;
int* arr;
}intstack_t;
// char stack definition
typedef struct CharacterStack {
int top;
unsigned capacity;
char* arr;
}charstack_t;
//Stack functions
// int stack functions
intstack_t* create_intstack(int);
void destroy_intstack(intstack_t*);
void intstack_push(intstack_t*, int);
// char stack functions
charstack_t* create_charstack(int);
void destroy_charstack(charstack_t*);
void charstack_push(charstack_t*, char);
Majority of the function declarations (and indirectly, their respective macros) have been removed, as they all essentially function the same. I'm only concerned about the push function macro as provided. The other macros are really there to show what kind of usecase I intend. Obviously the macro used in push using _Generic will not work as intstack_t or charstack_t are not primitive types.
The goal is for the user to be able to use push(stack, data) where the stack can be a variable of either type intstack_t* or charstack_t* and the statement push(stack, data) will be transformed into intstack_push(stack, data) or charstack_push(stack, data) respectively.
_Generic will work with any complete type other than a Variable Length Array. And although you cannot associate incomplete types with values in an _Generic invocation, there is no problem with pointers to incomplete types.
So your push macro will work just fine, even if used in a context where instack_t and charstack_t are opaque.
Sample on coliru: http://coliru.stacked-crooked.com/a/7d9b181af2429c5e
I am learning C and I am having some trouble with a bit of homework I was given.
I am attempting to use a linked list that I have implemented as part of one header inside of another header. My implementation of the list includes a typedef that looks like this:
typedef struct queue_T
{
int count;
struct member_T * first;
struct member_T * last;
} * queue_T;
The above typedef is inside of one source file (.c). I am currently attempting to write a second source file that makes use of this type. Inside this source file, I attempted to declare some queue_T variables for use as global variables. I did so like this:
#include <math.h>
#include "mathfns.h"
#include "queue.h"
queue_T primes;
queue_T squares;
queue_T cubes;
primes = new_queue();
squares = new_queue();
cubes= new_queue();
new_queue() is my initializer function for the queue_T type and mathfns.h is the header file associated with the source file that you're looking at immediately above this paragraph. The above declarations of queue_T variables are defaulting to integers when I attempt to compile and when I attempt to initialize the variables it is generating an error. How can I avoid this? Should I #include the"queue.h header in the mathfns.h file
Thank you.
As I wrote in comments, you cannot perform function calls outside a function. You cannot even execute assignment statements outside a function, though you can provide constant initializers for global variables, and the syntax resembles an assignment statement. Initializers are not executable, however -- they are handled by the system outside the scope of program execution (which you can take as a reason for why you cannot perform function calls in them).
Presumably, function new_queue() both allocates a new struct queue_T and initializes it, then returns a pointer to the caller. That's fine and useful, but what if you just want to initialize an existing struct queue_T structure? Indeed, if you want to provide pre-initialized global objects of that type, such a facility is exactly what you need. For example:
static struct queue_T primes_struct = { 0, NULL, NULL };
queue_T const primes = &primes_struct;
/* ... */
But writing a literal structure initializer like that is tedious and error-prone. After all, what if the structure definition is changed after that code is written? In fact, if you simply want to initialize all members of a struct to zero / NULL, the conventional form of the initialzer is just { 0 } (a single element). But even that can end up not being what you want under some modifications.
An alternative would be to have your queue.h declare a macro that can be used to initialize an empty struct queue_T, and use that everywhere (including in function new_queue(), so as to be certain the same initialization is performed everywhere). Thus, somewhere in queue.h you might have ...
#define EMPTY_QUEUE { 0, NULL, NULL }
... and in mathfns.c you could do this:
static struct queue_T primes_struct = EMPTY_QUEUE;
queue_T const primes = &primes_struct;
That way, if ever you modify struct queue_T, you can make a corresponding change to the macro instead of modifying any code in source files that simply use that structure.
I am not trying to have two different structs with the same name, but rather defining the same exact struct two different times (probably in different header files).
For example:
struct foo {
int bar;
};
struct foo {
int bar;
};
gives an error.
The way to do this is to surround your struct with preprocessor instructions
#ifndef STRUCT_FOO
#define STRUCT_FOO
struct foo {
int bar;
};
#endif /* STRUCT_FOO */
#ifndef STRUCT_FOO
#define STRUCT_FOO
struct foo {
int bar;
};
#endif /* STRUCT_FOO */
this has the effect of only defining struct foo once. In combination with the commonly accepted practice of putting such an item in a file called foo.h, like so
#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
struct foo {
int bar;
};
#endif /* INCLUDE_FOO_H */
it also protects against a person doing
#include "foo.h"
#include "foo.h"
(rest of code)
As far as redefining the struct, that is not permitted in the C language; however, you can do some things that approximate a non-full redefine. I recommend avoiding them, as they tend to only make the code more obscure and difficult to maintain.
No.
There is absolutely no point in doing this. If you have a structure that is to be used by multiple compilation units, put it in a .h header file, and #include it from those .c files. Or, if you need it in multiple header files, just include the common header file from those.
Now if you don't need the actual structure definition, but rather just need to declare that it exists (so you can create pointers to said struture), you can use a forward declaration:
struct foo; // defined elsewhere
void somefunc(struct foo *ptr);
Short answer: No
The compiler isn't that smart - you already have struct foo, so you can't have another struct foo even if you think it is the same as the first one.
No.
You should seperate the struct in another header, it sounds like you may be organizing your code poorly and should rethink the design.
You could use a ifndef:
#ifndef NAMEDEF
struct name {
int val;
};
#define NAMEDEF
#endif
Although, I must reiterate that you need to rethink how your header files are designed and put this struct in a common header.
Its also possible to use a foreward declaration:
struct name;
void function() {
}
Having the following piece of code:
File: types.h
typedef struct Struct_A_T
{
int A;
char B;
float C;
}Struct_A;
File: code.c
#include "types.h"
void Function(const void *const ptr)
{
Struct_A localStruct = *((Struct_A *)ptr);
localStruct.A = 1000;
localStruct.B = 250;
localStruct.C = 128.485;
}
File: main.c
#include "types.h"
void Function(const void *const ptr);
int main(void)
{
Struct_A MyStruct1 = {2, 5, 2.8};
float local = 24.785;
/* Correct call */
Function(&MyStruct1);
/* Incorrect call!!! */
Function(&local);
}
And knowing that a pointer to void can be used as a "generic" pointer. How can I detect inside "Function" that the type passed in the void pointer is the correct in order to avoid the run time error provoked by the last call in the file main.c?
There's no way to do it using language features. It can only be done manually.
I, for one, use the following technique in debug builds of the code
typedef struct Struct_A_T
{
int A;
char B;
float C;
#ifdef DEBUG
unsigned signature;
#endif /* DEBUG */
}Struct_A;
i.e. in debug configuration I introduce an additional field into the structure. Each object of that struct type has to have that field initialized with some pre-determined "unpredictable" signature value specific for this type, like
#define STRUCT_A_SIGNATURE 0x12345678
which is easy to do if all structures are created in some centralized fashion (like allocated dynamically or initialized by a dedicated function). This might be more cumbersome if there's no such centralized location. But that the price we sometimes have to pay for safety. For example, in your example case that would be
Struct_A MyStruct1 = {2, 5, 2.8, 0x12345678 };
BTW, designated initializers might make such initializations more stable and it easier to read.
And then, in order to convert pointers from void * to the specific type I use the following cast macro
#ifdef DEBUG
#define TO_STRUCT_A(p)\
(assert((p) == NULL || ((Struct_A *)(p))->signature == STRUCT_A_SIGNATURE),\
(Struct_A *)(p))
#else /* DEBUG */
#define TO_STRUCT_A(p) ((Struct_A *)(p))
#endif /* DEBUG */
meaning that inside your Function you'd do
Struct_A localStruct = *TO_STRUCT_A(ptr);
which with very high probability will trigger assertion failure if a pointer to wrong type is passed to Function.
This all can (and should) be implemented using a more generic set of macros, of course.
Obviously, this only works for struct types, into which you can inject that additional signature field. Another potential problem with this approach is that by introducing an extra field into the structure in debug builds one can potentially cause the behavior of debug and release build to diverge.
You can't, that's the primary downside of void*, you have no way to determine what is being pointed to. You just have to know.
You may use sizeof to compare sizes of the struct to that which void* points points to. This is not a sufficient but necessary condition that a pointer to your struct type is passed to Function. BTW the property of languages with the possibility to check metadata (incl. types) of variables and wider is called reflection. It is available in many modern languages and some bits have been included recently in C++11, but C still lacks it.
If I have a source.c file with a struct:
struct a {
int i;
struct b {
int j;
}
};
How can this struct be used in another file (i.e. func.c)?
Should I create a new header file, declare the struct there and include that header in func.c?
Or should I define the whole struct in a header file and include that in both source.c and func.c? How can the struct be declared extern in both files?
Should I typedef it? If so, how?
if this structure is to be used by some other file func.c how to do it?
When a type is used in a file (i.e. func.c file), it must be visible. The very worst way to do it is copy paste it in each source file needed it.
The right way is putting it in an header file, and include this header file whenever needed.
shall we open a new header file and declare the structure there and include that header in the func.c?
This is the solution I like more, because it makes the code highly modular. I would code your struct as:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
I would put functions using this structure in the same header (the function that are "semantically" part of its "interface").
And usually, I could name the file after the structure name, and use that name again to choose the header guards defines.
If you need to declare a function using a pointer to the struct, you won't need the full struct definition. A simple forward declaration like:
struct a ;
Will be enough, and it decreases coupling.
or can we define the total structure in header file and include that in both source.c and func.c?
This is another way, easier somewhat, but less modular: Some code needing only your structure to work would still have to include all types.
In C++, this could lead to interesting complication, but this is out of topic (no C++ tag), so I won't elaborate.
then how to declare that structure as extern in both the files. ?
I fail to see the point, perhaps, but Greg Hewgill has a very good answer in his post How to declare a structure in a header that is to be used by multiple files in c?.
shall we typedef it then how?
If you are using C++, don't.
If you are using C, you should.
The reason being that C struct managing can be a pain: You have to declare the struct keyword everywhere it is used:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
While a typedef will enable you to write it without the struct keyword.
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
It is important you still keep a name for the struct. Writing:
typedef struct
{
/* etc. */
} MyStruct ;
will just create an anonymous struct with a typedef-ed name, and you won't be able to forward-declare it. So keep to the following format:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
Thus, you'll be able to use MyStruct everywhere you want to avoid adding the struct keyword, and still use MyStructTag when a typedef won't work (i.e. forward declaration)
Edit:
Corrected wrong assumption about C99 struct declaration, as rightfully remarked by Jonathan Leffler.
Edit 2018-06-01:
Craig Barnes reminds us in his comment that you don't need to keep separate names for the struct "tag" name and its "typedef" name, like I did above for the sake of clarity.
Indeed, the code above could well be written as:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, this is actually what C++ does with its simpler struct declaration, behind the scenes, to keep it compatible with C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Back to C, I've seen both usages (separate names and same names), and none has drawbacks I know of, so using the same name makes reading simpler if you don't use C separate "namespaces" for structs and other symbols.
For a structure definition that is to be used across more than one source file, you should definitely put it in a header file. Then include that header file in any source file that needs the structure.
The extern declaration is not used for structure definitions, but is instead used for variable declarations (that is, some data value with a structure type that you have defined). If you want to use the same variable across more than one source file, declare it as extern in a header file like:
extern struct a myAValue;
Then, in one source file, define the actual variable:
struct a myAValue;
If you forget to do this or accidentally define it in two source files, the linker will let you know about this.
a.h:
#ifndef A_H
#define A_H
struct a {
int i;
struct b {
int j;
}
};
#endif
there you go, now you just need to include a.h to the files where you want to use this structure.