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 */
Related
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.
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.
I've a slight problem with my include files and I've made a simplified mockup of my problem.
Say I'm compiling some source that requires a header file named
header.h
Which has in it:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
#include element.h
typedef struct {
Element *list;
} Thing;
#endif
Then I have another header file defining that Element and also requiring header.h.
element.h
#ifndef ELEMENT_INCLUDED
#define ELEMENT_INCLUDED
typedef struct Element;
#include header.h
void * func(Thing *myThing);
#endif
I then run into a problem because element.h can't know what the Thing type is; we haven't reached that definition in header.h because we needed to include element.h.
I thought I could maybe solve my problem for "forward typedefing" a Thing type in element.h and right before the void * func prototype like
typedef struct thing Thing;
Then this just creates another problem and the compiler complains that there are conflicting types for Thing.
How do I get out of this mess?
Your main problem is that there is a cyclic dependency between the 2, yet you're using guard macros. The files are included almost as if by copy-paste - one of the files has to be included before the other, so you cannot have such cyclic dependency. Rethink your structure.
Declare/define the basic data type in 1 place, then the derived/composite data types using that, and finally the functions that take those types as arguments/return values.
Also, typedef struct Element; is invalid typedef.
Simplest way to solve your problem is to isolate your struct definition in its own header, protected by #ifndef/#define as usual. If you don't want a header file for this single struct, define the struct twice and protect its definition by another #ifndef/#define this way:
#ifndef __BOOLEAN_ENUM__
#define __BOOLEAN_ENUM__
enum boolean
{
false = 0,
true = 1
};
#endif
header.h should not include element.h. Otherwise you have circular dependency.
The code you posted has a large number of errors. (In future, post real code that you tried to compile, instead of making stuff up as you go in the edit box). Here is an example, where I have omitted the header guards for brevity:
// header.h
struct Element; // actually not necessary, but may help with readability
typedef struct
{
struct Element *ptr;
} Thing;
and
// element.h
#include "header.h"
struct Element
{
int x;
};
typedef struct Element Element; // optional
void * func(Thing *myThing);
It would be possible to also place typedef struct Element Element; in header.h and use Element *ptr inside the definition of Thing, it is a matter of taste as to which way you prefer. Some people disapprove of using typedef with structs at all in C, however I like it as it means that a typo leads to an immediate compilation error, instead of silently creating a new type.
If you also want element.h to not depend on header.h, you can use the same technique with Thing. You need to give it a struct tag , like how struct Element has.
Just step back from the C code and thing of the overall program design.
It is clear that the "Thing" struct must depend on the "Element" struct in element.h. However, it doesn't make any sense to use functions that depend on "Thing" from inside the element header. It rather makes most sense that functions using "Thing" should be inside the "Thing" header.
If you look at it with an object-oriented approach, which you should no matter programming language, then Element is a class, Thing is a class. The function could either be a member function of Thing, or it could be a non-related function using that class.
What you would do in object-oriented C, is to declare both "Element" and "Thing" as incomplete types in their respective headers. The type definition is hidden from the caller, and only present in those header's respective C files, called element.c and thing.c. All member functions dealing with the respective classes will be declared in the headers and defined in the C files. (This design is also sometimes called opaque type or opaque pointers.)
Functions using either class will then simply include the needed header.
I'm struggling with a design issue, and I'm trying to find the "Best Practice" answer for my situation.
Say I have a file called Logger.c (And Logger.h) that is responsible for logging actions in my program.
I want logger to be referenced by all my modules, so each module's has a
#include Logger.h.
Say I have a module called NTFS.c that is responsible for interaction with the NTFS FS, This module has special structs that are defined in its header, for example: NTFS_Partition.
Here is the problem:
On one hand, I want logger to be able to print to a log file a formatted representation of NTFS_Partition, and by that I must #include NTFS.h in Logger.h.
(Inside Logger.h)
#include NTFS_Partition
VOID Log_Partition(NTFS_Partition *part);
On the other hand, I am not sure Logger should re-reference modules that reference him.
Currently I'm seeing a two main choices:
1.Logger.h includes NTFS.h, and NTFS.c include Logger.h (This works)
2.I create a new header file called NTFS_Types.h that would be shared accross all the
modules, and would only contain the deceleration of NTFS structs (like NTFS_Partition).
Thanks a lot,
Michael.
You can create a shared header where all your structs are defined.
// structs.h
struct NTFS_Partition { .. };
struct FAT32_Partition { .. };
struct FAT16_Partition { .. };
Include it in logger.h.
// logger.h
#include "structs.h"
VOID Log_Partition(NTFS_Partition *part);
VOID Log_Partition(FAT32_Partition *part);
VOID Log_Partition(FAT16_Partition *part);
And include the logger.h in various source files.
// NTFS.c
#include "logger.h"
// FAT32.c
#include "logger.h"
// FAT16.c
#include "logger.h"
In C++, it's better to keep different irrelevant class definitions in different header files. But in C, placing different struct definitions in separate headers is probably an overkill.
It isn't entirely clear whether you are coding in C or C++; I'm going to assume C (so no overloaded function names, etc). It seems to me that you need to 'forward declare' your structures. In Logger.h, you write:
#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED
struct NTFS_Partition; // No details - just the name (3 times)
struct FAT16_Partition;
struct FAT32_Partition;
...
void Log_NTFS_Partition(struct NTFS_Partition *part);
void Log_FAT16_Partition(struct FAT16_Partition *part);
void Log_FAT32_Partition(struct FAT32_Partition *part);
#endif // LOGGER_H_INCLUDED
This is all the information that a general client (of Logger.h) needs to know.
If a specific client is dealing with NTFS partitions, then it will not only include Logger.h but also NTFS.h, which will provide the full definition of struct NTFS_Partition { ... };, so the client can create instances of the structure and populate it with data. The code that implements the logging, Logger.c, will also include Logger.h and NTFS.h (and FAT16.h and FAT32.h), of course, so that it too can reference the members of the structures.
The header for a service (such as Logger.h) should provide the minimal amount of information that the clients of the service need for compilation. The implementation file may need more information, but can collect the extra information from headers that provide it.
One advantage of using the struct tag notation is precisely that it can be repeated as often as necessary without messing anything up. If you don't have C11, you can't repeat a typedef, so if you write:
typedef struct NTFS_Partition NTFS_Partition;
you must only include that line once. The difficulty is making sure that it is only defined once. For that, you probably use a header such as FSTypes.h to define the file-system typedefs that is properly protected by header guards and is included in any file that needs any of the typedefs. You can then reference the types without the preceding struct keyword.
If you code in C++, the typedef isn't necessary; struct NTFS_Partition; declares that there is such a structure type and also declares NTFS_Partition as a name for that type. If your code is bilingual, use the typedef version; it works in both C and C++.
Note that if your functions such as Log_NTFS_Partition() take an actual structure instead of a pointer to a structure, then you have to have the definition of the structure in scope. If the functions only take pointers, though, a forward declaration is sufficient.
I've got two header files, each requiring a type defined in the other. When I try to compile, I get an error regarding an unknown type name. (If I provide only struct declarations and not definitions, I get an incomplete-types error.) What's a solution that will let me share these structs properly?
Right now, my code looks rather like the following (just imagine the #ifndef preprocessor directives etc.):
<headerA.h>
#include "headerB.h"
typedef struct {
mytypeB myB;
} mytypeA;
<headerB.h>
#include "headerA.h"
typedef struct {} mytypeB;
void foo( mytypeA * myA);
You should forward-declare the struct mytypeA instead of including headerA.h:
Inside headerB.h:
struct mytypeA; // <<<--- Forward declaration
void foo(struct mytypeA* myA);
This works because you are not using the actual mytypeA, only a pointer to it. You cannot pull the same trick with headerA, because mytypeA includes the actual mytypeB.
You can forward declare a structure without needing to define the whole thing.
These SO questions might help you since it is related to your question.
undefined C struct forward declaration
How to declare a structure in a header that is to be used by multiple files in c?