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.
Related
In C, you can use the static keyword to make global variables and functions private to the file in which they're defined. The compiler won't export these symbols, and thus the linker will not allow other modules to use these definitions.
However, I'm struggling to figure out how to restrict a struct definition such that it doesn't get added as an exported symbol that could accidentally be used by another module during the linking process. I would like to restrict this to the only file in which its defined.
Here are my attempts thus far which I've been struggling with.
// structure that is visible to other modules
struct PrivateStruct
{
int hello;
int there;
};
// this seems to throw an error
static struct PrivateStruct
{
int hello;
int there;
};
// i would ideally like to also wrap in the struct in a typedef, but this definitely doesn't work.
typedef static struct PrivateStruct
{
int hello;
int there;
} PrivateStruct;
Edit: I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler? It would be nice to prevent this behavior.
I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler?
No. Whether you are talking about structure tags or typedefed identifiers, these have no linkage. Always. There is no sense in which it would be reasonable to say that they are exported symbols.
This is among the reasons that header files are used in C. If you want to use a structure type in one compilation unit that is compatible with a structure type in a different compilation unit then compatible structure type declarations must appear in both. Putting the definition in a header makes it pretty easy to achieve that.
yes..... you can use pointers to the structure, and to the outer world it is not deferrable. Normally, that requires two header files, the first is the public one:
header mystruct.h
This header is public, used by client code.
struct my_opaque;
/* we cannot use *p fields below, as the struct my_opaque is
* incompletely defined here. */
void function_using(struct my_opaque *p, ...);
header mystructP.h
This header is private, and includes the public header file to maintain the
API to the client code.
#include "mystruct.h" /* safety include (1) */
struct my_opaque {
/* ... */
};
implementation mystruct.c
In implementation code, we include the private header file, and so, we have full access to the structure fields.
#include "mystructP.h"
/* we have full definition, as we included mystructP.h */
void function_using(struct my_opaque *p,
...)
{
... /* we can use p->fields here */
}
(1) the safety #include allows to change the struct my_opaque and the API functions, and the compiler to blame you if you change something in the api to the caller modules, forcing you to recompile if you change something in that API.
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.
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 */
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?