For the sake of this question, please disregard the software-design problems related to mutual dependencies, and focus on the technical aspect.
Please consider two header files, a.h and b.h. File a.h defines some struct which b.h requires. However, b.h also defines a struct which a.h requires.
As I understand it, a usual technique to resolve this circular #include dependency, is in b.h instead of including a.h, it would forward-declare the struct definition it requires from a.h. This would look something like this:
a.h
// No nice typedef
struct MyThing_t {
// ...
};
B.h
// Other things omitted
typedef struct MyThing_t MyThing;
// ... proceed using MyThing
As I understand it, this is supposed to compiler and work.
But - why does it work? How is the compiler aware of the name MyThing_t when it's compiling b.h? What is the mechanism here?
Also - why shouldn't I include the typedef also in a.h, for use by using modules which a.h doesn't have a circular dependency with?
The most straightforward way to deal with this situation is to define the struct in a different header, like basic.h, or some such, and have a.h and b.h both include that header. Because in b.h this
typedef struct MyThing_t MyThing
forward declaration declares an opaque type that allows you to only use a MyThing* pointer. Because b.h has no idea of what the size or memory layout of the struct actually is. This is actually a very common C idiom, as it allows encapsulation of the internals of a struct, and allows declaration in the header file of functions that operate on that pointer without needing to know the implementation.
It's typedef *struct* MyThing_t MyThing;; no declaration is needed for struct Mything_t (which can cause bugs, so typedefs-for-everything is a good idea).
I find it's better to write a single fwd.h file (or for large projects, per directory) with all the typedefs in it, and include that at the beginning of all other headers.
Incidentally, you should avoid names ending with _t unless you work for POSIX.
As I understand it, this is supposed to compiler and work.
Yes and no. Each header can be #included in a source file independently of the other, but B.h does not provide a definition of struct MyThing_t. Where no definition is in scope, that's an incomplete type, which greatly limits what you can do with it.
But - why does it work? How is the compiler aware of the name
MyThing_t when it's compiling b.h?
If it is not already aware of struct MyThing_t before it reaches the typedef, the typedef makes it aware.
What is the mechanism here?
A structure type with a tag can be used without a prior declaration or definition of that type, but only in the ways that an incomplete type may be used. This is what allows structures to contain pointers to objects of their own type. It can be used more generally to declare pointers to the type in question, and it can also be used in typedefs. On the other hand, incomplete types may not be used in any way that requires knowledge of their storage size or (for structure and union types) their members' names or types.
Also - why shouldn't I include the typedef also in a.h, for use by
using modules which a.h doesn't have a circular dependency with?
I don't know, why shouldn't you? That would be more typical than splitting them up. You do need to be careful about declaring the same typedef twice, though. It's legal to do so in the latest versions of C, but it was not allowed in C90 and C99.
Related
I'm trying to include 3rd party libraries into the .c file but it gives either redefinition or conflicting types error since it has typedef structs with the same name.
I've tried to include guards after reading some answers here in SO and obviously directly changing the typedef on the .h file has solved the problem.
e.g. (Also have to change the functions return type)
// stack.h
typedef struct item stack_item;
// queue.h
typedef struct item queue_item;
However, the original code is as follows:
// stack.h
typedef struct item item;
// queue.h
typedef struct item item;
It throws the following error:
In file included from test.c:5:0:
Queues/queue.c:6:8: error: redefinition of ‘struct item’
struct item {
^
In file included from Stacks/stack.c:4:0, from test.c:4:
Stacks/stack.h:6:16: note: originally defined here
typedef struct item item;
^
I would like to know what is the standard way to solve this, instead of changing the definitions in the .h file
C has only one namespace for structure tags, which also contains the tags of unions and enumerations. You cannot use two different structure types with the same tag in the same scope. There is a different namespace that contains typedefed identifiers, among other things, but again, one type name can mean only one thing in any given scope.
However, in practice, structure names are significant only at compile time. If you are using packaged, pre-compiled versions of the third-party libraries then probably all you need to worry about is the headers. You might be able to use the preprocessor to change one or both of the tags within the scopes of your program's translation units. For example,
#define item stack_item
#include <stack.h>
#undef item
#define item queue_item
#include <queue.h>
#undef item
Your code would then use struct stack_item and / or the typedef stack_item for the one, and struct queue_item and / or queue_item for the other. Be aware that there is a risk of that having a broader effect than you want -- changing structure member names, for example. Additionally, although it has a decent chance to work, it is technically non-conforming to call any functions that have parameters or return types derived from or containing instances of the original structure types (with some caveats).
In the event that that does not work, you could also consider performing equivalent edits by hand to produce local versions of the headers for use by your project only. This would allow you to be more precise about what gets changed, but using these headers still suffers from the conformance issues described above.
If you must use both libraries in the same translation unit and you want to ensure that your code conforms to the standard, then you're out of luck. The only conforming alternative is to modify and rebuild one or both libraries so that they no longer have name collisions.
The title says it all! Can it be done and if so, how?
A little background if you must know: We've recently taken over a project from another team (because they were disbanded) that has strongly interdependent headers. Changing that is difficult without yanking stuff out of the header file they logically belong in and stuffing somewhere else, where it does not logically belong.
Until now, the approach to deal with this has been to simply forward declare structs and functions from other headers where necessary. That worked fairly well until we got into the typedef'd function pointers, which is how our callback function types are currently implemented.
We would like to solve this without having to disturb the logic of the header files if possible, but have been unable to forward declare those typedefs to far. Various searches for 'forward declare typedef' only yielded results about forward declaring typedef'd structs, which doesn't help us at all.
Example:
a.h
/* #file a.h */
#ifndef _a_
#define _a_
#include "b.h"
// Definitions that need stuff from b.h
typedef void (some_callback_function) (uint32_t, uint16_t, uint8_t*);
// More definitions that need stuff from b.h
#endif
b.h:
/* #file b.h */
#ifndef _b_
#define _b_
#include "a.h"
// Definitions that need stuff from a.h
struct some_struct {
// Stuff
some_callback_function *cb_someting; // ERROR: some_callback_function not defined yet!
// Other stuff
};
// More definitions that need stuff from a.h
#endif
EDIT: In this example, the problem arises when including a.h. The first thing it does before declaring anything itself in including b.h, which in turn also includes a.h before declaring anything. The guards prevent an endless loop here, but I still end up with a.h trying to declare something using stuff that will later be declared in b.h but has not yet been. Thus a forward declaration should does the trick for structs and functions.
If typedefs cannot be forward declared, I could think of two ugly workarounds:
Remove the includes from the header files and leave it up to the user to include the other headers. As far as I know, this is considered bad coding styles as headers should include their dependencies themselves.
Move the typedefs before the #includes. I am not sure whether this is actually bad style, but my intuition tells me that putting anything before the #includes is evil. Also, this only works as long as the typedefs do not need anything from another header file.
In C often structs are typedefed to avoid writing struct everywhere.
When using this names as opaque pointer parameters in headers you have to forward declare them. It is rather annoying that the whole typedef has to be duplicated.
Example:
some header defines some types:
typedef struct sBlaBlaFooBar{
int someData;
}BlaBlaFooBar;
Some other header uses this structure as pointer parameter. But to avoid huge include dependencies BlaBlaFooBar.h should not be included and just a forward declaration is used.
So you have to write typedef struct sBlaBlaFooBar BlaBlaFooBar; to forward declare it.
That does bother me is the redundancy that i have to know the tag name of the structure because normally it does not matter. And if it is changed, all the forward declarations also have to be changed even if the typename is the same.
Is there some smart way around this?
more detailed explanation:
a lot of headers with structure definitions (that may be also composed structures (just to show deep dependency graphs))
s1.h
s2.h
s3.h
s4.h
a BlaBlaFooBar header with a BlaBlaFooBar structure that is a composite of all these.
Additional structures BlaBlaBarFoo with similar topology (from other sub structures)
then modules that defines new structures NewStruct and functions NewStruct_create(NewStruct* out, const BlaBlaFooBar* in); that processes
the above structures as input. These headers only need the typedefs and only the implementation has to know about exact BlaBlaFooBar structure definitions.
Addional modules that only work on NewStruct and to not necessarily have to be recompiled if BlaBlaFooBar changes.
So to avoid these kind of dependencies the structures have to be forward declared in the header and the c-file includes the definition.
Use 2 include files:
blabla.h
#include "light_dependencies.h"
typedef struct sBlaBlaFooBar BlaBlaFooBar;
blabla_internal.h
#include "blabla.h"
#include "heavy_dependencies.h"
struct sBlaBlaFooBar {
...
};
blabla.c
#include "blabla_internal.h"
/* Here is code which deals with the internals of the struct */
usercode.c
#include "blabla.h"
/* Here is code which only passes struct pointers around */
As for working on a larger project, I want to throw in some own types (e.g. myType). The "rushing in"-approach would be, to put those typedefs into an header (lets say myType.h), together with a bunch of functions working on those types.
If I use the new type somewhere, I include myType.h to my source-file. Fine.
But if I want to use the new type somewhere as an argument in a function-signature, I need to include the myType.h to the header of the module containing the function. With one or another typedef, this seems to be okay for me, but the more types I have, the more includes in headers I need, possible including further header, while using type including other own types. This is resulting in what I call "dependency hell".
Is there a clever, stylish, best practice, what-so-ever way to solve this dilemma?
I'm aware of the possibility to pass those types as void-pointer, casting them back inside the function, but then I loose important type-checking from the compiler.
Furher, extern is considered worst-practice around here..
EDIT:
In detail:
myType.h:
#include "otherType.h"
typedef struct {
char Name[32];
int Size;
otherType someType;
} myType;
processSomeHow(myType _myType, int NewSize);
otherType.h
#define SOME_CONST 32
typedef struct { [...] } otherType;
someModule.h:
#include "myType.h"
int specialProcessSomeHow(myType _myType);
someModule.c:
int specialProcessSomeHow(myType _myType)
{
int Size = 64;
return(processSomeHow(_myType, Size));
}
Now I include otherType.h indirectly to someModule.h, even worse, I include it to every module, that includes someModule.h. Now I have a SOME_CONST everywhere and it's hard to figure out, from where it comes. I have to maintain two include trees.
like in the gtk library you can use one headfile and split it on your needs.
type.h
- myType.h
-- someType.h
- otherType.h
- List item
and on your CONST-Problem:
If you just need it for one c.file. Don't use them in HeaderFile.
And you could name them like "MY_TYPE_SOME_CONST" or "OTHER_TYPE_SOME_CONST";
//EDIT:
to make it clear: just add 'this.h' file and name it.
#ifndef TYPE_H_
#define TYPE_H_
#include myType.h
#include someType.h
#include otherType.h
#endif /* TYPE_H_ */
now you can use "#include this.h" for each file you need your types.
(this.h is not real, name it to something unique)
You can (and probably should) use forward declarations for your custom types. See details here: typedef stuct with forward declaration in C
Your interfaces (the headers) should have incomplete types (i.e. pointers to your custom types) and inside the source code (c files) you should include the My_Type.h.
You're worrying unnecessarily : There is no 'dependency hell', precisely because you are giving the compiler all the information it needs to do it's job.
Here's my rules for this:
Always, always use header guards.
Every .h file should
explicitly #include every other .h file it needs in order to compile,
and no more.
So if b.h uses a type from a.h, then b.h must #include "a.h". If b.c uses functions from a.h, but b.g doesn't use types from it, then b.c should #include a.h.
There's no need for extern keyword on functions in .h files, because IIRC modern compilers deduce this correctly.
Using extern for global variables may well be frowned on, with good
reason.
Cluttering of global namespace. C++ namespaces address this, but in C you have to use naming conventions for all global types, functions and #defines. Pick a convention that works for you : I've seen teams successfully use a LETTER-DIGIT-DIGIT prefix for every source file, so foo.h might become (for example) B04_foo.h, and all functions/types get the same B04_ prefix. It's a bit crude, but it works. As I say, pick one that works for you.
The rule in C against declaring a struct's members more than once seems to me to be the main reason that include guards are necessary. If we have the following in "header.h":
struct s {
int a;
char b;
};
and the file "a.h" #include's header.h, then we cannot include both "a.h" and "header.h" as then struct s is defined twice.
My question is, what is the problem with doing this? Why can't multiple identical definitions of structs be allowed? This would remove the need for include guards, and clean up C header files enormously.
The rule in C is that multiple declarations are allowed, but only one definition. For some reason, specifying the members of a struct is called "definition", even though it is not defining a variable or a function.
Re-defining a structure is extremely error-prone. Even in your simple example, if a.h includes a #pragma that adjusts structure packing or alignment before it includes "header.h", then the two definitions may not necessarily be the same any longer. This type of problem would be hard to debug because it would be dependent on the header include order.
In general, there are a number of things that can go wrong when you allow data type re-definition. In exchange, you don't get any real benefits from it other than being able to drop the header guards. Header guards solve the problem and are only a minor level of overhead that doesn't clutter the code unreasonably. Some compilers support a #pragma once (or similar) that acts as an include guard but only requires one line of code.
In my personal opinion, it would be a better idea to guard against multiple inclusion by default and require guard macros only on headers that are designed to be included multiple times (leave the overhead to the use case that is in the vast minority). That's not the way C was originally implemented, though (plus it would make the pre-processor more complicated), so it's extremely unlikely that it will ever change.
Well, it's like C works... It's definition because it provides the actual implementation of the object.
You can't define them twice, because as #Kirilenko said, the definition is providing the implementation of the object. However, I am wondering if your question is also asking something else.
Edit: Change instantiation to definition.
Your definition of s
struct s {
int a;
char b;
};
would go into a .c file, or at least you would either extern the struct in a .h file and put the structure instantiation in a .c file, or use typedef in the .h file.
typedef struct s {
int a;
char b;
} my_struct_type;
Even if you wanted the struct defined in a .h file, you could prevent its "being defined twice" by bracketing like so
Edit: Removed underscores from macro
#ifdef MY_STRUCT_DEFINED
struct s {
int a;
char b;
};
#endif