Interdependent headers not compiling - c

I have 2 headers that depend on each other, both are guarded. But compilation fails as if the type weren't declared:
error: unknown type name Type_1
the first header:
#ifndef HEADER1_H
#define HEADER1_H
#include "header2.h"
typedef struct {
int a;
char *b;
} Type_1;
void function(Type_3 *type_3);
#endif
second header
#ifndef HEADER2_H
#define HEADER2_H
#include "header1.h"
typedef struct {
int a;
char *b;
Type_1 *c;
} Type_2;
typedef struct {
int a;
char *b;
Type_2 *c;
} Type_3;
#endif
How to solve it without resorting to hacks?

You must forward declare at least one struct. I'd personally put them all in one header, since there's not that much there.
First header:
#ifndef HEADER1_H
#define HEADER1_H
#include "header2.h"
typedef struct Type_1 {
int a;
char *b;
} Type_1;
void function(Type_3 *type_3);
#endif
The second header:
#ifndef HEADER2_H
#define HEADER2_H
struct Type_1;
typedef struct {
int a;
char *b;
struct Type_1 *c;
} Type_2;
typedef struct {
int a;
char *b;
Type_2 *c;
} Type_3;
#endif

Move all your types definitions to one files and functions declarations to another one.
header1.h
#ifndef HEADER1_H
#define HEADER1_H
typedef struct {
int a;
char *b;
} Type_1;
typedef struct {
int a;
char *b;
Type_1 *c;
} Type_2;
typedef struct {
int a;
char *b;
Type_2 *c;
} Type_3;
#endif
header2.h
#ifndef HEADER2_H
#define HEADER2_H
#include "header1.h"
void function(Type_3 *type_3);
#endif

As you use your structures as imcomplete data types, forward declaration is enough:
#ifndef HEADER2_H
#define HEADER2_H
struct Type1;
typedef struct Type1 Type1;
typedef struct {
int a;
char *b;
Type_1 *c;
} Type_2;
typedef struct {
int a;
char *b;
Type_2 *c;
} Type_3;
#endif
Apply same technique to second file. Though, in source code, you need to include header if you don't use your structures as incomplete types. More information about incomplete data types is available in this MSDN article

Related

Not sure how to include functions from multiple C files [duplicate]

This question already has an answer here:
How to split a C program into multiple files?
(1 answer)
Closed 28 days ago.
I am not sure what is the best practice for including multiple c files. I was given two header files for an assignment, and am now required to create the corresponding c files.
Right now my issue is that I need to use functions defined in course.c in student.c, however, I am running into a linker issue that I am not sure how to resolve. The way I am currently including files is by creating multiple function definitions!
student.h
#include <stdbool.h>
#include <stdint.h>
struct course;
struct student;
struct student_id {
uint16_t sid_year;
uint32_t sid_serial;
};
struct student* student_create(struct student_id, bool grad_student);
void student_free(struct student*);
void student_take(struct student *s, struct course*, uint8_t grade);
int student_grade(struct student*, struct course*);
double student_passed_average(const struct student*);
bool student_promotable(const struct student*);
student.c
#include "student.h"
#include "course.c"
struct student
{
<Fields>
};
struct student* student_create(struct student_id id, bool grad_student)
{
<definition>
}
void student_free(struct student* s)
{
<definition>
}
void student_take(struct student *s, struct course* c, uint8_t grade)
{
<definition>
}
int student_grade(struct student* s, struct course* c)
{
<definition>
}
double student_passed_average(const struct student* s)
{
<definition>
}
bool student_promotable(const struct student* s)
{
<definition>
}
course.h
#include <stdint.h>
/** Course subjects. */
enum subject {
SUBJ_ENGI,
SUBJ_CIV,
SUBJ_ECE,
SUBJ_MECH,
SUBJ_ONAE,
SUBJ_PROC,
SUBJ_CHEM,
SUBJ_ENGL,
SUBJ_MATH,
SUBJ_PHYS,
};
struct course;
struct course* course_create(enum subject, uint16_t code);
enum subject course_subject(const struct course*);
uint16_t course_code(const struct course*);
void course_hold(struct course*);
void course_release(struct course*);
int course_refcount(const struct course*);
course.c
#include "course.h"
#include <stdio.h>
#include <stdlib.h>
struct course {
<fields>
};
struct course* course_create(enum subject sub, uint16_t code)
{
<definition>
}
enum subject course_subject(const struct course* c)
{
<definition>
}
uint16_t course_code(const struct course* c)
{
<definition>
}
void course_hold(struct course* c)
{
<definition>
}
void course_release(struct course* c)
{
<definition>
}
int course_refcount(const struct course* c)
{
<definition>
}
Which gives the following errors:
gcc *
multiple definition of `course_create'; ... first defined here ...
multiple definition of `course_subject'; ... first defined here ...
multiple definition of `course_code'; ... first defined here ...
multiple definition of `course_hold'; ... first defined here ...
multiple definition of `course_release'; ... first defined here ...
multiple definition of `ref_count'; ... first defined here ...
I am assuming this is an issue with me including course.c in student.c, but I need to include course.c to get the course structure definition. So I am wondering how I can go about retrieving the definition of struct course without using the line #include course.c
Do not #include source files. Move the structure definitions from the source files to the appropriate header files. Use include guards to avoid header files being processed more than once.
Below is a complete example that will compile cleanly with
gcc course.c student.c main.c
This is essentially an application of the answer to How to split a C program into multiple files?, but with functions and structures.
course.h:
#ifndef COURSE_H
#define COURSE_H
#include <stdint.h>
enum subject {
SUBJ_ENGI,
SUBJ_CIV,
SUBJ_ECE,
SUBJ_MECH,
SUBJ_ONAE,
SUBJ_PROC,
SUBJ_CHEM,
SUBJ_ENGL,
SUBJ_MATH,
SUBJ_PHYS,
};
struct course {
enum subject subject;
};
struct course *course_create(enum subject, uint16_t);
enum subject course_subject(const struct course *);
uint16_t course_code(const struct course *);
void course_hold(struct course *);
void course_release(struct course *);
int course_refcount(const struct course *);
#endif
student.h:
#ifndef STUDENT_H
#define STUDENT_H
#include <stdbool.h>
#include <stdint.h>
#include "course.h"
struct student {
char name[128];
};
struct student_id {
uint16_t sid_year;
uint32_t sid_serial;
};
struct student *student_create(struct student_id, bool);
void student_free(struct student *);
void student_take(struct student *, struct course *, uint8_t);
int student_grade(struct student *, struct course *);
double student_passed_average(const struct student *);
bool student_promotable(const struct student *);
#endif
course.c:
#include <stddef.h>
#include <stdint.h>
#include "course.h"
struct course *course_create(enum subject sub, uint16_t code)
{
return NULL;
}
enum subject course_subject(const struct course *c)
{
return SUBJ_ENGI;
}
uint16_t course_code(const struct course *c)
{
return 0;
}
void course_hold(struct course *c)
{
}
void course_release(struct course *c)
{
}
int course_refcount(const struct course *c)
{
return 0;
}
student.c:
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "course.h"
#include "student.h"
struct student *student_create(struct student_id id, bool grad_student)
{
return NULL;
}
void student_free(struct student *s)
{
}
void student_take(struct student *s, struct course *c, uint8_t grade)
{
}
int student_grade(struct student *s, struct course *c)
{
return 0;
}
double student_passed_average(const struct student *s)
{
return 0.0;
}
bool student_promotable(const struct student *s)
{
return false;
}
main.c:
#include <stdio.h>
#include "course.h"
#include "student.h"
int main(void)
{
struct student_id id = { 0, 0 };
struct student *stu = student_create(id, 0);
struct course *cour = course_create(SUBJ_MATH, 0);
puts("Hello world.");
}

How to forward declare a typedef structure in C which has no tag

file1.h: Library code. CANT change it
#ifndef FILE1_H_
#define FILE1_H_
typedef struct
{
int x;
} MY_STRUCT;
#endif /* FILE1_H_ */
file2.h: user defined. can be changed. How to forward declare above typedef struct which has no tag ?
#ifndef FILE2_H_
#define FILE2_H_
struct MY_STRUCT;
void print(struct MY_STRUCT * obj);
#endif /* FILE2_H_ *
file2.c: user defined. can be changed
#include "file2.h"
#include "file1.h"
#include <stdio.h>
void print(struct MY_STRUCT * obj)
{
printf("x: %d", obj->x);
}
main.c
#include "file2.h"
#include "file1.h"
int main(void){
MY_STRUCT obj1;
obj1.x = 100;
print(&obj1);
}
The code can be seen here. https://paiza.io/projects/wa2PCvUswWyyAzdxxjggxQ?language=c
It's not possible to "forward-declare" a typedef . You will have to give the struct a tag, e.g.:
typedef struct my_struct MY_STRUCT;
// ... later
struct my_struct
{
int x;
};

How to handle circular dependencies in typedef'd structures

I have two modules, a and b.
a.h:
#ifndef A_H_
#define A_H_
#include "b.h"
typedef struct {
b_t *b;
...
} a_t;
#endif // A_H_
b.h:
#ifndef B_H_
#define B_H_
#include "a.h"
typedef struct {
a_t *a;
...
} b_t;
#endif // B_H_
How do I alter this so that it will compile? (I want to keep two separate compilation units.)
edit: I forgot to make the structure members pointers.
Use forward declarations:
a.h:
struct b_t;
typedef struct a_t {
struct b_t *b;
} a_t;
b.h:
struct a_t;
typedef struct b_t {
struct a_t *a;
} b_t;
[This answer only applies to the original question, where pointers were not used as the struct members].
that's impossible. it's naturally not possible to have such structure.
let's say:
struct a {
struct b b;
int i;
};
struct b {
struct a a;
int i;
};
what do you expect from sizeof(struct a)? this struct will explode, it's impossible to compile.
however, it can be compiled if you have them turn to pointers:
struct a;
struct b {
struct a *ap;
};
struct a {
struct b *bp;
};
this code indeed compiles: http://ideone.com/GKdUD9.
Exactly this isn't possible. You can't have a struct be its own member, not even transitively. This is however possible when you use a pointer. Use a structure declaration:
typedef struct a_struct *a_t;
typdef struct {
a_t a;
} *b_t;
typedef struct a_struct {
b_t b;
} a_t;
[This answer only applies to the original question, where pointers were not used as the struct members].
You can't.
Essentially you have
typedef struct {
b_t b;
} a_t;
typedef struct {
a_t a;
} b_t;
and no forward declaration can help you. You have an impossible structure here: the sizeof would be infinite.

In C, how do you use a struct in the main function that was declared in a header file?

In C, I need to declare a struct linked list in a header file. Within the main of my .c file, how do I declare a new instance of my struct? Also should I use typedef for my struct?
In your header:
struct mystruct
{
int a;
int b;
};
in .c file include (#include "header.h") the header, then use in main:
struct mystruct obj1;
obj1.a=0;
obj1.b=0;
In your header file add the definition and typedef
typedef struct linked_list_node_st {
int val;
struct linked_list_node_st *next;
} Linked_List_Node;
In main.c, call the struct using the typedef.
#include <stdio.h>
#include <stdlib.h>
#include "structure.h"
int main(int argc, const char * argv[]) {
Linked_List_Node *node;
node = malloc(sizeof(Linked_List_Node));
node->next = 0;
node->val = 1;
return 0;
}
U have struct in header, and want that struct in main.c?
Just include it with #include "header.h" directive in your main.c, and start to use struct.
You use typedef when u want to make "your variable" in c, like:
typedef int INTEGER;
INTEGER number;
So u use typedef for closer indentify your struct, for you or for readers.

C recursive header file inclusion problem?

Suppose you have to related structures defined in 2 header files like below:
a.h contents:
#include b.h
typedef struct A
{
B *b;
} A;
b.h contents:
#include a.h
typedef struct B
{
A *a;
} B;
In such this case, this recursive inclusion is a problem, but 2 structures must point to other structure, how to accomplish this?
Don't #include a.h and b.h, just forward-declare A and B.
a.h:
struct B; //forward declaration
typedef struct A
{
struct B * b;
} A;
b.h:
struct A; //forward declaration
typedef struct B
{
struct A * a;
} B;
You might want to think about how tightly coupled the classes are. If they're very tightly coupled, then maybe they belong in the same header.
Note: you'll need to #include both a.h and b.h in the .c files to do things like a->b->a.
Google C/C++ guidelines suggests:
Don't use an #include when a forward declaration would suffice
That'd mean:
a.h contents:
typedef struct B B;
typedef struct A
{
B *b;
} A;
b.h contents:
typedef struct A A;
typedef struct B
{
A *a;
} B;
If you prefer something a bit safer (but longer to compile) you can do this:
a.h contents:
#pragma once
typedef struct A A;
#include "B.h"
typedef struct A
{
B *b;
} A;
b.h contents:
#pragma once
typedef struct B B;
#include "A.h"
typedef struct B
{
A *a;
} B;
You pre-define the struct only, in that way you can still declare a pointer:
In a.h:
typedef struct B_ B;
typedef struct A_
{
B *b;
} A;
Note how I use separate names for the typedef and struct tags, to make it a bit clearer.
This will cut it in C:
typedef struct B B;
typedef struct A A;
struct A { B *b; };
struct B { A *a; };
You can rearrange B and A as desired.

Resources