I checked SO for duplicates of this, but was unable to find an exact solution for my problem.
I have a header file NvCommon.h where I use an enum NV_DATA_TYPE. This enum is defined in another header NvDefs.h where I use a number of structs and enums from NvCommon.h. I can't build this due to circular dependency. I know that forwrd declaring enum is not possible.
In this situation what could be done? Is this a problem with my design? Do I have to introduce another header file to solve this?
I am no C expert. Please help me. My design may have issues and I know can fix this circular dependency by introducing another header file. What I would like to know is "is that the only way around". Looking for alternate solutions if available.
I will post the full code if it is helpful.
It can be useful to define enums in their own file(s), and if you do that here, your problem will disappear.
If I understand your question correctly, you've got something like this:
derpfoo.h:
#ifndef DERPFOO_H
#define DERPFOO_H
#include "derpbar.h"
typedef struct {
char *nothing;
} FOO;
BAR foo (BAR derp) {
return derp;
}
#endif
derpbar.h:
#ifndef DERPBAR_H
#define DERPBAR_H
#include "derpfoo.h"
typedef struct {
char *nothing;
} BAR;
FOO bar (FOO derp) {
return derp;
}
#endif
and then a simple derp.c:
#include "derpfoo.h"
#include "derpbar.h"
int main (void) {
return 0;
}
A friend of mine presented me with this problem in some SDL code a while ago, and it took me a while to understand both why he was doing what he was doing and how to fix it reasonably.
The intention of separating the code like this is that derpfoo and derpbar are logically separate, but they are also, sadly, mutually dependent. The simplest solution I've found to such a thing is to combine them and split them according to anatomy rather than logic like so:
derpstructs.h:
#ifndef DERPSTRUCTS_H
#define DERPSTRUCTS_H
typedef struct {
char *nothing;
} FOO;
typedef struct {
char *nothing;
} BAR;
#include "derpfunctions.h"
#endif
derpfunctions.h:
#ifndef DERPFUNCTIONS_H
#define DERPFUNCTIONS_H
#include "derpstructs.h"
BAR foo (BAR derp) {
return derp;
}
FOO bar (FOO derp) {
return derp;
}
#endif
and still a simple derp.c:
#include "derpstructs.h"
#include "derpfunctions.h"
int main (void) {
return 0;
}
Note that derpstructs.h includes derpfunctions.h at the end rather than at the beginning. This is not, strictly speaking, necessary, but if you do intend to have them include each other, you must include the function definitions after the struct definitions that they depend on, in all possible inclusion paths. Moving on...
This solution works, but it's not exactly sticking with the original philosophy that caused the problem to begin with -- that the two parts are logically separate, and should be kept so in the code.
The answer to both is to split everything up further, and tweak the inclusion paths even more.
derpfoostructs.h includes derpbarstructs.h first and then defines struct FOO and then at the end optionally includes derpfoofunctions.h and derpbarfunctions.h.
derpbarstructs.h includes derpfoostructs.h first and then defines struct BAR and then at the end optionally includes derpfoofunctions.h and derpbarfunctions.h.
derpfoofunctions.h includes derpfoostructs.h and derpbarstructs.h first, then includes derpbarfunctions.h, and then defines its functions.
derpbarfunctions.h includes derpfoostructs.h and derpbarstructs.h first, then includes derpfoofunctions.h, and then defines its functions.
derp.c includes derpfoostructs.h and derpbarstructs.h and then includes derpfoofunctions.h and derpbarfunctions.h, and then goes on to do whatever else it needs to do.
This satisfies both of the desired requirements. It eliminates circular dependencies, and still maintains logical separation of the two logically separate code units. You get two files to edit when you change from project to project instead of one, but it at least keeps the mutable code apart from the immutable. That, and it's the only solution I've found.
Hope this helped. Good luck on your projects.
Circular dependencies might mean that you're overdesigning your interface. Merge both files into Nv.h. If this trivially solves the problem, this means you were incorrectly designing the interface.
Check this out
How to properly declare and define variables, libraries, functions , etc. This might be relevant.
I tried modeling this problem based on your description. In my implementation, I tested three things (1) declaring but not defining NV_DATA_TYPE in NvDefs.h, (2) declaring and defining NV_DATA_TYPE in NvDefs.h, and (3) defining NV_DATA_TYPE in NvDefs.h, but declaring it NvCommon.h. Also, as your description provided, I created some structs in NvCommon.h and accessed those objects in NvDefs.h. In every case--with and without guards in the header files--the code compiled and executed with correct results.
Is it possible that your circular dependency is somewhere else in your header files besides the NV_DATA_TYPE enum?
Related
I am currently "playing" around in a quite big and old codebase and, quite unfortunately, it has no fixed style attached to it. So it was just made to work but that also means that quite a lot of it can be described as spaghetti code.
I came across something that I do not fully undersand. Compiler is from ARM/KEIL and it is for an embedded system.
first file:
fileA.c
// prototype
int GetSomething( int a );
// implementation
int GetSomething( int a) {
DoSomething();
}
second file:
fileB.c
// prototype
int GetSomething( int a )
void main ( void ) {
GetSomething(10);
}
There are no headers which have a declaration for the function GetSomething but the function is still correctly linked. Originally, there are a extern keyword in the second file in the declaration of GetSomething, but with or without that results in the same binary. The code has been tests and works.
I've seen Stackoverflow Question but that doesn't seem to cover my case as it seems to have nothing to do with the extern keyword.
I hope that somebody can explain that to me or tell me what is going on. Thanks.
Using header files and #include directives are just a more organized and neater way to use various parts of code in a program at different places.
When you do something like #include "header.h" a copy of header.h is put into the file.
So when you write
GetSomething( int a );
you are essentially doing an alternative to what
#include would normally do.
Another important detail is that function prototypes have the extern storage class specifier by default.
One thing you should keep in mind is that declaring function prototypes across your files manually can result in error prone and hard to maintain code. So it is best to utilize header files and #include directives.
I am confused by my actual problem... Could also be my mistake
Short description with code:
rtc.h
#ifndef RTC_H_
#define RTC_H_
typedef struct timestamp_t
{
uint8_t year,month,day,hour,minute,second;
}timestamp_t;
#endif /* RTC_H_ */
lpwa.h
#ifndef LPWA_H_
#define LPWA_H_
#include "rtc.h"
timestamp_t lpwa_ntp_to_stamp(char*); //shows error: unknown name timestamp_t
#endif /* LPWA_H_ */
lpwa.c
#include "lpwa.h"
timestamp_t lpwa_ntp_to_stamp(char *text) //no problem
{
...
}
If I copy the typedef struct to lpwa.h it says "confliction types for timestamp_t"
Am I missing something or is this just not possible?
This is an answer compiled from my debugging recommendations which helped OP to find the actual problem:
The shown code should not exhibit the described problem. This actually is helpful information, because it means that the structure of your actual code is different and you need to find that difference to trace the problem to the root.
The problem is probably in the include order, aka include tree, being different than you think.
Inserting #error Header A is compiled #error Header B is compiled generously in all likely and unlikely places of your project will give you an idea of the actual include tree, allowing you to look for differences to the imagined include tree. (Use #warning if your compiler supports it, then you get more than only the first #error encountered.)
The constructive way to debug this is to make a StackOverflow-style minimal reproducible example.
If making a classic MRE/MCVE ( http://stackoverflow.com/help/mcve ) seems too much work (it is not, trust me), then try making a MRE of what you think happens, from scratch. That will at least show you that what you think happens is NOT what actually happens. This is also helpful information, though making use of it requires experience and discipline. (Thanks for not feeling mocked here.)
Keep in mind that each source code file "*.c" is the root of another include tree.
Playing with #error will also alert you of the possible problem that you look at different files (e.g. in your editor) than the compiler actually processes. (Again, not mocking. That happens more often, to me, than I'd like to admit....)
Above is general.
Specifically in your case, I suspect that there is a hidden/indirect #include "lwpa.h" inside rtc.h, between the shown include and the shown typedef. (And I think you confirmed that.)
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.
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