I've got two structures in two different header files, let's say:
header1.h:
#ifndef HEADER1_H
#define HEADER1_H
#include "header2.h"
typedef struct
{
Struct2 s;
} Struct1;
#endif
header2.h:
#ifndef HEADER2_H
#define HEADER2_H
#include "header1.h"
typedef struct
{
Struct1* s;
} Struct2;
#endif
As you can see i declare Struct2 in Struct1 and pointer to Struct1 in Struct2. Obviously when i try to compile this it gives me an error: unknown type name ‘Struct1’ or 'Struct2'. Is there any way to do this or i must change my conception?
If you really want to do this, you can, you just need to use partial declarations before really declaring each structure:
header1.h
#ifndef _HEADER1_H
#define _HEADER1_H
#include "header2.h"
struct struct1
{
struct struct2 s2;
};
#endif
header2.h
#ifndef _HEADER2_H
#define _HEADER2_H
struct struct1;
struct struct2
{
struct struct1 *s1;
};
#endif
Related
I have this situation:
A.h and B.h
In A.h:
typedef struct TypeA TypeA_t;
struct TypeA {
...
TypeA_t *a;
void (*doSomething)(TypeB_t *);
};
In B.h:
typedef struct TypeB TypeB_t;
struct TypeB {
...
TypeB_t *b;
TypeA_t something;
};
What is the correct way to include header files in each file?
If I include A.h in B.h and B.h in A.h I get:
error: unknown type name 'TypeB_t' in A.h
and
error: unknown type name 'TypeA_t' in B.h
I found a similar question here but it doesn't work in my case.
The way you've defined your code, TypeA can live with a forward reference to TypeB, but TypeB needs the full declaration of TypeA to compile.
In other words, you need to do two things. First forward define TypeB in a.h before your class definition (because pointers can work with partial definitions):
//a.h
typedef struct TypeB TypeB_t;
typedef struct TypeA TypeA_t;
struct TypeA {
...
TypeA_t *a;
void (*doSomething)(TypeB_t*);
};
And then include a.h from b.h to get the declaration for your class (because you use the full TypeA class as a field type):
// b.h
#include "a.h"
typedef struct TypeB TypeB_t;
struct TypeB {
...
TypeB_t *b;
TypeA_t something;
};
The typedefs can be moved to other header files, and use header guard macros to prevent multiple definitions:
At.h
#ifndef AT_H_INCLUDED_
#define AT_H_INCLUDED_
typedef struct TypeA TypeA_t;
#endif
Bt.h
#ifndef BT_H_INCLUDED_
#define BT_H_INCLUDED_
typedef struct TypeB TypeB_t;
#endif
A.h
#ifndef A_H_INCLUDED_
#define A_H_INCLUDED_
#include "At.h"
#include "Bt.h"
struct TypeA {
TypeA_t *a;
void (*doSomething)(TypeB_t *);
};
#endif
B.h
#ifndef B_H_INCLUDED_
#define B_H_INCLUDED_
#include "Bt.h"
#include "A.h"
struct TypeB {
TypeB_t *b;
TypeA_t something;
};
#endif
.c files shouldn't need to include "At.h" or "Bt.h". The inclusion of "At.h" and "Bt.h" can be policy restricted to be included only by the main header files. Including "A.h" will fully define TypeA_t. Including "B.h" will fully define TypeB_t (and will also fully define TypeA_t). They can be included in any order.
Suppose I have such a project structure:
main.c
#include "hashtable.h"
#include "list.h"
int main()
{
hash_table ht = calloc(1, sizeof(htable));
cmp_function f;
TLDI list;
return 0;
}
hashtable.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _HASH_TABLE_
#define _HASH_TABLE_
#include "list.h"
typedef int (*hash_function)(void*, int);
typedef struct _hasht_{
int maxElemNumber;
hash_function hf;
TLDI* key_array;
} htable, *hash_table;
void test2(cmp_function cmp);
#endif
list.h
#include "hashtable.h"
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
typedef int (*cmp_function)(void*, void*);
typedef struct _node_ {
void *info;
struct _node_ *pre, *urm;
} TNode, *TLDI;
int test(hash_table ht);
#endif
and another two C files:
hash_func.c
#include "hashtable.h"
void test2(cmp_function cmp)
{
printf("test\n");
}
list_func.c
#include "list.h"
int test(hash_table ht)
{
return 1;
}
I want to use in hashtable.h a typedef from list.h, it's typedef struct...},*TLDI;. In the same way, list.h uses a typedef struct ...},*hash_table; from hashtable.h. Can I do something like this or I'm wrong? Cause I get this error while compiling whole project:
In file included from hashtable.h:7,
from main.c:1:
list.h:14:10: error: unknown type name ‘hash_table’
14 | int test(hash_table ht);
In file included from hashtable.h:7,
from hash_func.c:1:
list.h:14:10: error: unknown type name ‘hash_table’
14 | int test(hash_table ht);
I'm not strong in typedef and headers, but if I would get an answer to this question or at least a source from where I could find out more about them I would be very grateful.
Two headers that rely to each other are not a show stopper if well-formed. What I observe is that your include guards don't enclose the full header but only part of it, this I think is wrong. The right way to use include guards is shown in this
example header some_component.h:
#ifndef SOME_COMPONENT_H
#define SOME_COMPONENT_H
// include whatever you need here (*after* the opening guard):
#include "some_other_component.h"
// start type definitions and declarations *after* includes:
struct some_component_t {
// ...
};
#endif
This way, you headers will work most consistently:
either read completely
or completely ignored
I advise you to avoid placing definitions before includes, as this allows you to modify the content of the included content. What looks like a tempting idea at first, turns into a confusing nightmare in the long run in the vast majority of cases.
Another point is that if the definitions in the two headers really rely on each other, you should rethink your design.
Also, it's not clear why void test2(cmp_function cmp); which relies on cmp_function is declared in hashtable.h and why int test(hash_table ht); which relies on hash_table is declared in list.h; to me this seems like you were mixing up things here. In other words, by switching places of some declarations, you'd get rid of most of the entanglement.
You should also know that typedefs and pointers are allowed on incomplete types, so it's possible to declare a pointer to a structure that is not yet defined. So, for example, the following compiles:
typedef int (*hash_function)(void*,int);
typedef int (*cmp_function)(void*,void*);
typedef struct _hasht_ hasht, *hash_table;
typedef struct _node_ TNode, *TLDI;
struct _node_ {
void *info;
struct _node_ *pre, *urm;
};
struct _hasht_{
int maxElemNumber;
hash_function hf;
TLDI* key_array;
};
... as does this (version without struct typedefs):
struct _node_ {
void *info;
struct _node_ *pre, *urm;
};
typedef int (*hash_function)(void*,int);
struct _hasht_{
int maxElemNumber;
hash_function hf;
struct _node_** key_array;
};
The overall interdependency of the headers is kind of ugly, but the errors can be corrected with some forward declarations:
hashtable.h
#ifndef _HASH_TABLE_
#define _HASH_TABLE_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _hasht_ htable, *hash_table;
typedef int (*hash_function)(void*,int);
#include "list.h"
struct _hasht_ {
int maxElemNumber;
hash_function hf;
TLDI* key_array;
};
void test2(cmp_function cmp);
#endif
list.h
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
typedef struct _node_ TNode, *TLDI;
typedef int (*cmp_function)(void*,void*);
#include "hashtable.h"
struct _node_ {
void *info;
struct _node_ *pre, *urm;
};
int test(hash_table ht);
#endif
I'm trying to define a structure as a typedef in a header file and use it in many sources. I found a similar answer in here but I'm not sure if a typedef can be defined as extern. Also msg_encoded should have a default value.
// lib.h
#ifndef lib_h
#define lib_h
struct msg_encoded_s
{
uint8_t msg[10];
int length;
} msg_encoded_default = {{0}, 0};
typedef struct msg_encoded_s msg_encoded;
#endif
// lib.c
#include "lib.h"
msg_encoded some_var;
// main.c
# include "lib.h"
int main(){
msg_encoded some_other_var;
}
main.o:(.bss.msg_encoded_default+0x0): multiple definition of
`msg_encoded_default'
A "declaration" like
struct msg_encoded_s {
...
} msg_encoded_default;
is actually both (1) a definition of a struct-type named msg_encoded_s and (2) the definition of a variable of this type named `msg_encoded_default.
Hence, if you include this header file in separate translation units, then you will redefine a variable named msg_encoded_default, which is not allowed.
To overcome this, write a header like...
typedef struct msg_encoded_s
{
uint8_t msg[10];
int length;
} msg_encoded;
extern msg_encoded msg_encoded_default;
An in exactly one translation unit write:
#include "myheader.h"
msg_encoded msg_encoded_default = {{0}, 0};
In all other translation units just write...
#include "myheader.h"
...
int test = msg_encoded_default.length; // or something like this
I have two header files
A.h
struct A { ... };
function declarations which use A
B.h
function declarations which use the struct A here, and have functions which also use A.
However, I want to call "A" B here. How can I do this? I want all the
functions in here use
struct B, which I want to be exactly the same as struct A since
An example of what I "want" to do, but uses defines and is probably the wrong way of doing things: (Note, it works perfectly how I want it to, but I don't think I should be using defines for this purpose, there is probably a better way of doing things)
A.h
#ifndef A_H
#define A_H
struct A {int x;};
void A_DoSomething(struct A* a);
#endif
B.h
#ifndef B_H
#define B_H
#include "A.h"
#define B A
void B_DoSomething(struct* B b) { A_DoSomething(b); }
#endif
So is there a way to do what I want without using define? I want to do this so I can reuse code. I.e., A is a linked list, B is a stack. I can completely define my stack data structure from a linked list.
EDIT: So basically B and A are equivalent, but for my B.h/B.c file, and any files using B.h, I just want to call the structure "B" and not "A"
I would use typedef and use 3 h-files to separate the common data structure from A and B. Something like:
MyNode.h:
#ifndef MyNode_H
#define MyNode_H
typedef struct Node
{
void *data;
struct Node *next;
} Node;
#endif
A.h:
#ifndef A_H
#define A_H
#include "MyNode.h"
typedef Node A;
/* Declare functions for implementing a linked list using type A */
#endif
B.h:
#ifndef B_H
#define B_H
#include "MyNode.h"
typedef Node B;
/* Declare functions for implementing a stack using type B */
#endif
Main.c:
#include <stdio.h>
#include "A.h"
#include "B.h"
int main(void) {
/* Here A and B can be used as types, example: */
A list = {NULL, NULL};
B stack = {NULL, NULL};
return 0;
}
In my C project, I have a header file with a declaration of a struct (with an alias) and a header file with functions that accept that struct as an argument (using the alias). I am receiving the error expected ')' before '*' token on the function. From researching, I think this indicates that the alias is not visible in the function's namespace. I have a fairly convoluted include web that I believe may be causing this. Here is a simplified example.
Struct declaration header:
#ifndef STRUCTHEADER_H_
#define STRUCTHEADER_H_
#endif /* STRUCTHEADER_H_ */
#ifndef STRUCTFUNCTIONS_H_
#include "structFunctions.h"
#endif
struct myStruct{
};
typedef struct myStruct mys;
Struct function header:
#ifndef STRUCTFUNCTIONS_H_
#define STRUCTFUNCTIONS_H_
#endif /* STRUCTFUNCTIONS_H_ */
#ifndef STRUCTHEADER_H_
#include "structHeader.h"
#endif
void func(mys* s);
main.c:
#ifndef STRUCTHEADER_H_
#include "structHeader.h"
#endif
int main(int argc, char* argv[]){
return 0;
}
However, when I change main.c to this:
#ifndef STRUCTFUNCTIONS_H_
#include "structFunctions.h"
#endif
int main(int argc, char* argv[]){
return 0;
}
the error goes away. Am I using include wrong?
You need to change structHeader.h so that it declares the structure before it includes structFunctions.h, because the function definition needs to refer to the alias. In C, you can only refer to names that have been previously declared.
#ifndef STRUCTHEADER_H_
#define STRUCTHEADER_H_
#endif /* STRUCTHEADER_H_ */
struct myStruct{
};
typedef struct myStruct mys;
#ifndef STRUCTFUNCTIONS_H_
#include "structFunctions.h"
#endif