Circular dependency between struct and function in C - c

I have the following files:
A.h
#ifndef __A_H_
#define __A_H_
#include <B.h> // contains foo_t
typedef struct {
foo_t foo;
...
} baz_t;
#endif
B.h
#ifndef __B_H_
#define __B_H_
#include <A.h> // contains baz_t
typedef struct {
...
} foo_t;
extern int useful_func(baz_t d);
#endif
When I compile this B.h refuses to compile complaining error: unknown type name 'baz_t'
I am assuming this error is owing to circular dependency between the two files. But I am wondering how do I forward declare baz_t to solve this? I found answers relating to circular dependencies between structs. But I am unsure how I would solve this. I would appreciate some help here. I am looking for a strictly C99 solution.
EDIT
I previously forgot to mention this but I have already used include guards.
A very obvious solution as suggested by user KamilCuk is moving useful_func to A.h. This has also occured to me but software organization wise useful_func unfortunately belongs to B.h. This problem could be a reflection of a poor design as well.

You can use forward declaration as follows:
struct foo;
typedef struct {
struct foo foo;
...
} baz_t;
And then use it normally on B.h
That said, circular dependencies can be avoided is you define everything on a third header that you use as interface. It would be cleaner, but it's not always possible.

Typically, one would pass pointers to structures rather than passing them by value. If that would be acceptable, things are easy, since C compilers will accept a declaration:
void doSomethingWithAFoo(struct foo *it);
without regard for whether they have seen any definition for struct foo. Indeed, compilers will even accept function definitions like:
void doSomethingWithAFooTwice(struct foo *it)
{
doSomethingWithAFoo(it);
doSomethingWithAFoo(it);
}
without having to know or care about whether, where, or how struct foo is defined.
Note that an advantage of using struct tag syntax rather than typedef names is that prototypes using the struct tag syntax don't require declaring or defining anything that can't be harmlessly redeclared arbitrarily many times.

Related

Problem with C nested structure. error: invalid use of incomplete typedef

For the sake of simplicity I'm going to recreate the actual situation with dummy structures. I have this structure (not my code, I can't edit it):
// private_header_a.h
struct A_s{
int a1;
};
// header_a.h
typedef struct A_s A_t;
Then in one of my headers I extended it this way:
// my_header.h
typedef struct B_s{
A_t* a_f;
int b1;
} B_t;
Now, in my function, I have:
B_t* b;
// Initialization and some other code
b->b1 = 4; // Just an example and compiler does not give any error
// Some other code
b->a_f->a1;
This last line of code makes the compiler throw this error:
error: invalid use of incomplete typedef ‘A_t’ {aka ‘struct A_s’}
Where is the error?
EDIT: the piece of code that triggers the compiler has header_a.h and my_header.h included. private_header_a.h cannot be included directly as not installed (I should copy-paste it, but frankly I would like to avoid to do that)
The compiler error is probably intentional - the library's designers don't want you using A_t directly in that sort of way.
When a struct is only declared in a library's public header file, and only defined in the library's private implementation files, that means you're not supposed to know or care about its members or even size. So looking up that the struct has a member named a1 and writing b->af->a1 is not the intended use. This arrangement is called an "opaque handle". A few of its benefits are that the library keeps your application code from initializing or changing members in ways that don't make sense, and a future version of the library can change the names, numbers, and meanings of the members without breaking your application code.
(Also, how did you get a valid pointer for b->af without doing malloc(sizeof(A_t)) or similar? That sizeof would also cause a compiler error about the incomplete struct type.)
When a library uses an opaque handle, since you can't create any such objects yourself, it will typically provide functions that create the objects for you. Look for public functions in the library with names including init, create, open, etc. which return an A_t* pointer, and read their documentation. Usually there will also be a corresponding destroy, cleanup, close, etc. function which the program should call later when the library object is no longer needed. (In the case of some very simple handles, the function which creates the object might say instead you should just pass the pointer to free. But only do this if the documentation says to!)
Here's two fundamental rules:
Each c file is compiled separately
When you #include a file, think of it as directly replacing the #include line with the contents of the file being included.
Therefore, you are compiling a piece of source code that looks like this:
struct A_s {
int a1;
};
typedef struct B_s {
A_t* a_f;
int b1;
} B_t;
void foo() {
B_t* b;
}
This code doesn't know what A_t is. You've never defined that in the code that's visible to the compiler.
A trivial way to fix this is to replace A_t with struct A_s.

Using external header file with definitions different from the ones used internally

Suppose you are writing a library that uses internally certain data structures, and wants to export to the user only a subset of them (or hide the exact type using something like void *). The definitions for all the structs and functions used in the library are in a header library.h, which will be used when building the library.
Is it considered good practice to also produce another copy of library.h that would not be used during the build process but only by users linking to the library?
For example suppose the library internally uses the following library.h:
#ifndef LIBRARY_H
#define LIBRARY_H
struct myStruct {
int some_x;
void (*some_callback)(void);
};
typedef struct myStruct *myStruct_t;
#endif
While we would like to hide the definition of myStruct to the user, so we export a header library.h that is:
#ifndef LIBRARY_H
#define LIBRARY_H
typedef void *myStruct_t;
#endif
Is it considered good practice to also produce another copy of library.h that would not be used during the build process but only by users linking to the library?
No. While the details of a best practice for what you want to do are probably a matter of taste, delivering headers not used during building is objectively not a good practice: You risk to introduce typing errors that are never catched when you build your project.
So, without going into details on how you should organize that, what you should definitely do is have each "private" header #include the respective "public" header and not repeat public declarations in the private header. For your example, this would look e.g. like:
library.h:
#ifndef LIBRARY_H
#define LIBRARY_H
typedef struct myStruct *myStruct_t;
// there's absolutely no need to use void * here. An incomplete struct
// type is perfectly fine as long as only pointers to it are used.
#endif
library_internal.h:
#ifndef LIBRARY_INTERNAL_H
#define LIBRARY_INTERNAL_H
#include "library.h"
struct myStruct {
int some_x;
void (*some_callback)(void);
};
#endif
Additional "best practice" notes:
Don't hide pointers behind typedefs. Most C programmers are well aware that a pointer is part of the declarator and expect to explicitly see a pointer when there is one. Dereferencing something that doesn't look like a pointer will just cause confusion for others reading the code. You also might confuse consumers of your library into expecting a myStruct_t to exhibit call-by-value semantics.
Don't define your own types with the _t suffix. At least in POSIX, this is reserved for the implementation (of the compiler/runtime). There's nothing wrong with defining a type of the same name as a struct tag.
Example with these additional suggestions:
library.h:
#ifndef LIBRARY_H
#define LIBRARY_H
typedef struct myStruct myStruct;
#endif
library_internal.h:
#ifndef LIBRARY_INTERNAL_H
#define LIBRARY_INTERNAL_H
#include "library.h"
struct myStruct {
int some_x;
void (*some_callback)(void);
};
#endif
Notice that the C standard doesn't guarantee that a pointer to void has a representation that is compatible with a pointer to a struct! Thus:
typedef struct myStruct *myStruct_t;
typedef void *myStruct_t;
these two are not compatible and cannot be used in a strictly conforming program.
Another thing is that you usually shouldn't hide pointers, unless needed. Consider for example the FILE in the standard library. Its contents are not defined anywhere, but all the functions specifically return a pointer to it and accept a pointer to it.
You can even use a simple struct declaration, instead of definition:
struct myStruct;
Then external users can define a variable as a pointer to it
struct myStruct *handle;
Or if you wish to hide the fact that it indeed is a struct, use a typedef:
typedef struct myStruct myStruct;
Then the users of the external interface can define their variables simply as
myStruct *handle;

C forward declaration query

I have a situation where two of my header files require the data structures defined in either one, i.e. no matter which order you include them it won't compile
however, one of the problem data structures only contains pointers to the data structure declared in the other header file so I would have though that technically it doesn't need to know at this point how big the data structure is so it shouldn't be complaining
A simplified example of what I mean is outlined below. I would have thought that the array of modes in Library doesn't need to know how big a Mode is, only how big a pointer to a Mode is therefore the compiler shouldn't complain if it hasn't yet seen the declaration of Mode in the other header file.
header_1.h
typedef struct
{
Mode **modes;
} Library;
header_2.h
typedef struct
{
int number;
char *name;
} Mode;
It doesn't need to know the size, but it must have seen a declaration. A forward declaration
typedef struct Mode Mode;
before the definition of struct Library suffices.
As currently written, your example does not show the mutual cross-referencing that you mention in the question.
The compiler must be told something about each type it uses. You could use in header_1.h just:
typedef struct Mode Mode;
typedef struct
{
Mode **modes;
} Library;
That would make it compile, at least. The compiler doesn't need the details, but it does need to know that Modes is a type.
Edit:
Note that header_2.h should be modified for this to work. You have to ensure that each typedef appears just once. After you have the typedefs in place, you specify the structure content (definition) once, and you omit the keyword typedef and the typedef name from the structure definition. And you have to decide on exactly the cross-references will be managed. For example, should header_1.h include header_2.h anyway.
I don't remember encountering a case where I really needed mutually referencing structures (in quite a long time programming — long enough that I could have forgotten a example). I do now remember a case of structures mutually referencing each other; it was in a version of make originally written for Minix. I still regard such a requirement as somewhat 'pathological' (or, if you prefer, as a 'code smell') and as something to be avoided whenever possible. If you really must manage it, then the section below explains how I'd go about doing it (and more or less how the make program did go about it).
Mutually-referencing structures
If you truly have two mutually referencing structures, you should (re)consider why you think two headers are better than one. If you still need two headers, you use an idiom like:
header_1.h
#ifndef HEADER_1_H_INCLUDED
#define HEADER_1_H_INCLUDED
#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif
struct Library
{
...
Mode **modes;
...
};
#endif /* HEADER_1_H_INCLUDED */
header_2.h
#ifndef HEADER_2_H_INCLUDED
#define HEADER_2_H_INCLUDED
#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif
struct Mode
{
...
Library **liblist;
...
};
#endif /* HEADER_2_H_INCLUDED */
The repeated typedef 'detection' code is not nice; a single header is better, in my estimation. However, you can include header_1.h and header_2.h above in either order and it should compile.
I believe this is happening because "Mode" is a type defined using typedef and its not the name of the struct. You will either need to explicitly forward declare it or you can try using the code structured as follows:
header_1.h
typedef struct
{
struct _Mode_t **modes;
} Library;
header_2.h
typedef struct _Mode_t
{
int number;
char *name;
} Mode;

Portable way to "unpoint" a pointer typedef?

This is unfortunately defined in some external library: cannot touch!
// library.h
typedef struct {
long foo;
char *bar;
/* ... (long & complex stuff omitted) */
} *pointer_to_complex_struct_t;
Now The Question: how to declare an complex_struct_t variable?
Ideal solution but not allowed! (cannot change external library):
// library.h
/* ... (long & complex stuff omitted) */
} complex_struct_t, *pointer_to_complex_struct_t;
// my.h
extern complex_struct_t my_variable;
Non-portable solution (gcc):
// my.h
extern typeof( * (type_placeholder)0 ) my_variable; // Thanks caf!
Other? Better? Thanks!
Bonus question: same question for a function pointer (in case there is any difference; I doubt it).
ADDED bonus: below is the exact same question but with functions instead of structs. This should not make any difference to the short answer ("No."), the only answer I was initially interested in. I did not expect some people to die trying to know and get my job done with creative workarounds, which is why I simplified the question from functions to structs (function pointers have special implicit conversion rules for convenience and confusion). But hey, why not? Let's get the copy-paste workaround competition started. Some workarounds are probably better than others.
///// library.h //////
// Signature has been simplified
typedef double (*ptr_to_callback_t)(long, int, char *);
// Too bad this is not provided: typedef double callback_t(long, int, char *);
///// my.h /////
// This avoids copy-paste but is not portable
typedef typeof( * (ptr_to_callback_t)0 ) callback_t;
extern callback_t callback_1;
extern callback_t callback_2;
extern callback_t callback_3;
// etc.
Short answer = no, there is currently no portable alternative to typeof
A basic copy-paste workaround works OK for functions but not for structs. The compiler will match the duplicated function types, but will not relate the duplicated struct types: a cast is required and the duplicated struct types will diverge without compilation warning.
No, unfortunately you cannot do it with standard C. With C++ a simple metafunction would do the trick though.
However you could just copy-paste the definition of the struct thus leaving the original untouched
typedef struct {
///same struct
} complex_struct_t;
The downside of this solution is that the expression &complex_struct_t won't be of type pointer_to_complex_struct_t, instead it will be of type pointer to unnamed struct {//your members};
You'll need reinterpret_casting, if you need that feature...
As written, the answer to your question is "no"; if all you have is a type definition of
typedef struct {...} *ptr_to_struct;
then there's no (standard, portable) way to extract the struct type. If you have to create an instance of the struct, the best you will be able to do is
ptr_to_struct s = malloc(sizeof *s);
and then refer to the fields in the struct using the -> component selection operator (or by dereferencing s and using the . operator, but you don't want to do that).
You asked if the same thing applied to function pointers; you really need to state exactly what you mean. If you have a situation like
typedef struct {...} *ptr_to_struct;
ptr_to_struct foo() {...}
then the situation is exactly like the above; you don't have a way to declare a variable of that type.
Make a local copy of the header file and include it instead of the original. Now you can do anything you want. If this library could change (update or anything else), you could write a little script to automate these steps and call it from your makefile whenever you compile. Just make sure to not blindly paste into the header, search for the specific line (} *pointer_to_complex_struct_t;) and throw an error if it is no longer found.
Maybe you have to be a bit careful with the search paths for includes if this header uses other headers of this library. Plus, with the order of includes if itself is included by other headers.
EDIT (for your real goal mentioned in a comment): You can't do this with function pointers. Just write the function you want with the signature of the typedef, and it will be compatible to the pointer and can be called by it.
How about:
pointer_to_complex_struct_t newStruct ( void ) {
pointer_to_complex_struct_t ptr =
(pointer_to_complex_struct_t) malloc ( sizeof (*pointer_to_complex_struct_t) );
return ptr;
}
You'd have to reference your newly created struct through ptr-> but you could create new ones.
Of course, this may or may not work, depending on how the struct is actually used. The example that comes to mind is: what if the struct ends with
char data[0];
and data is used to point into the memory following the structure.

Typedef and Struct in C and H files

I've been using the following code to create various struct, but only give people outside of the C file a pointer to it. (Yes, I know that they could potentially mess around with it, so it's not entirely like the private keyword in Java, but that's okay with me).
Anyway, I've been using the following code, and I looked at it today, and I'm really surprised that it's actually working, can anyone explain why this is?
In my C file, I create my struct, but don't give it a tag in the typedef namespace:
struct LABall {
int x;
int y;
int radius;
Vector velocity;
};
And in the H file, I put this:
typedef struct LABall* LABall;
I am obviously using #include "LABall.h" in the c file, but I am NOT using #include "LABall.c" in the header file, as that would defeat the whole purpose of a separate header file. So, why am I able to create a pointer to the LABall* struct in the H file when I haven't actually included it? Does it have something to do with the struct namespace working accross files, even when one file is in no way linked to another?
Thank you.
A common pattern for stuff like that is to have a foo.h file defining the API like
typedef struct _Foo Foo;
Foo *foo_new();
void foo_do_something(Foo *foo);
and a foo.c file providing an implementation for that API like
struct _Foo {
int bar;
};
Foo *foo_new() {
Foo *foo = malloc(sizeof(Foo));
foo->bar = 0;
return foo;
}
void foo_do_something(Foo *foo) {
foo->bar++;
}
This hides all the memory layout and size of the struct in the implementation in foo.c, and the interface exposed via foo.h is completely independent of those internals: A caller.c which only does #include "foo.h" will only have to store a pointer to something, and pointers are always the same size:
#include "foo.h"
void bleh() {
Foo *f = foo_new();
foo_do_something(f);
}
Note: The ISO C standard section on reserved identifiers says that all identifiers beginning with an underscore are reserved. So typedef struct Foo Foo; is actually a better way to name things than typedef struct _Foo Foo;.
Note: I have left freeing the memory as an exercise to the reader. :-)
Of course, this means that the following file broken.c will NOT work:
#include "foo.h"
void broken() {
Foo f;
foo_do_something(&f);
}
as the memory size necessary for actually creating a variable of type Foo is not known in this file.
Since you're asking a precise reason as to "why" the language works this way, I'm assuming you want some precise references. If you find that pedant, just skip the notes...
It works because of two things:
All pointer to structure types have the same representation (note that it's not true of all pointer types, as far as standard C is concerned).[1] Hence, the compiler has enough information to generate proper code for all uses of your pointer-to-struct type.
The tag namespace (struct, enum, union) is indeed compatible accross all translation units.[2] Thus, the two structures (even though one is not completely defined, i.e. it lacks member declarations) are one and the same.
(BTW, #import is non-standard.)
[1] As per n1256 §6.2.5.27:
All pointers to structure types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.
[2] As per n1256 §6.2.7.1:
two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: [does not concern us].
In
typedef struct A* B;
since all pointers' interfaces are the same, knowing that B means a pointer to a struct A contains enough information already. The actual implementation of A is irrelevant (this technique is called "opaque pointer".)
(BTW, better rename one of the LABall's. It's confusing that the same name is used for incompatible types.)

Resources