Forward declaration throws redefinition error - c

I have two .h files and a .c file as below
a.h
typedef struct mode_info_t_ mode_info_t;
struct common {
int create;
mode_info_t *mode_info;
};
b.h
typedef struct mode_info_t_ {
int primary;
int secondary;
} mode_info_t;
main.c
#include "a.h"
#include "b.h"
-----
When .c is compiled it throws below error -
b.h:17: error: redefinition of typedef 'mode_info_t'
a.h:50: error: previous declaration of 'mode_info_t' was here
What is wrong here experts?

Change b.h to this:
struct mode_info_t_ {
int primary;
int secondary;
};
If you need the typedef in b.h, have b.h include a.h. If you don't want to have b.h include a.h but still need the typedef in both, then take the typedef out of a.h and put it in c.h, and have both a.h and b.h include c.h.
I've actually done this before where I put all my forward declarations in a separate header, just to avoid the need for various headers including each other when it wasn't totally appropriate.

You have your b.h
typedef struct mode_info_t_ {
int primary;
int secondary;
}mode_info_t;
Then a.h
struct common {
int create;
mode_info_t *mode_info;
};
In your main.c just include b.h
#include "b.h"
#include "a.h"
int main()
{
}

When I compile the snippet you have given, I didn't get any errors and warnings. Can you show us your full code? It is possible to declare a structure and after that you can define it.
typedef struct Node Node;
struct Node {
int data;
Node *nextptr;
};
Here you are doing the same thing. So it not an error. You may have mishandled it somewhere.

Related

Header files recursion in C

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.

best way to access struct variable from header files that defined in c file

I declared a struct in main.c file and i have functions in func1.c func2.c func1.h func2.h files.
main.c:
#include <stdio.h>
#include "func1.h"
#include "func2.h"
struct mystruct{
someting
};
main(){
struct mystruct var ={...};
myfunc(var);
}
func1.h:
void myfunc(struct mystruct);
And definition is in func1.c. Similar for func2 files. I got compilation errors, it is obvious that problem is header file dont have declaration of mystruct and so cant use it.
So what is the way to overcome that problem? Adding a new header file for struct or using extern keyword what i read. What is approprite choice i couldnt figure out at that point.
struct mystruct{
//something
};
Should be defined in a header file which all your c files that need it has access to.
mytypes.h
#ifndef mytypes_h
#define mytypes_h
struct mystruct{
int something;
};
#endif
func1.h
#ifndef func1_h
#define func1_h
#include "mytypes.h"
void myfunc(struct mystruct);
#endif
func1.c
#include "func1.h"
void myfunc(struct mystruct){
//do soemthing with struct
}
Then your main can include func1.h which already mytypes.h
main.c
#include "func1.h"
int main(){
}

declare a struct in header as a typedef

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

Proper way to declare and use structures in C project?

I am building a project that I am trying to organize as follows:
main.c
globals.h
structures.h
FunctionSet1.c, FunctionSet1.h
FunctionSet2.c, FunctionSet2.h
etc.
I thought I could define a structure type in structures.h:
struct type_struct1 {int a,b;}; // define type 'struct type_struct1'
then declare a function1() returning a structure of type type_struct1 in FunctionSet1.h:
#include "structures.h"
struct type_struct1 function1(); // declare function1() that returns a type 'struct type_struct1'
then write function1() in FunctionSet1.c:
#include "FunctionSet1.h"
struct type_struct1 function1() {
struct type_struct1 struct1; // declare struct1 as type 'struct type_struct1'
struct1.a=1;
struct1.b=2;
return struct1;
}
Edit: with the corrected code above, the compiler returns
306 'struct' tag redefined 'type_struct1' structures.h
Is the file set good practice ?
What is the good practice to manage the structures ?
In your example, you declare a structure named type_struct in structure.h, then in FunctionSet1.h the structure that you are returning is type_struct, and in the .c it is called struct1.
So i think that the problem is that struct1 and type_struct are not recognized because they have never been defined ...
However, the organization of your files is fine.
Your general structure looks good. One thing you need to do, as zenith mentioned, is to put include guards into your header files. What that is is a set of #define's that make sure that the contents of the header are not included more that once in a given file. For example:
structures.h:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct type_struct1{
int a,b;
};
...
// more structs
...
#endif
FunctionSet1.h:
#ifndef FUNCTION_SET_1_H
#define FUNCTION_SET_1_H
#include "structures.h"
struct type_struct1 function1();
...
// more functions in FucntionSet1.c
...
#endif
main.c:
#inlcude <stdio.h>
#include "structures.h"
#include "FunctionSet1.h"
int main(void)
{
struct type_struct1 struct1;
struct1 = function1();
return 0;
}
Here, main.c includes structures.h and FunctionSet1.h, but FunctionSet1.h also includes structures.h. Without the include guards, the contents of structures.h would appear twice in the resulting file after the preprocesser is done. This is probably why you're getting the "tag redefined" error.
The include guards prevent these type of errors from happening. Then you don't have to worry about whether or not a particular header file was included or not. This is particularly important if you're writing a library, where other users may not know the relationship between your header files.
First of all, you have to declare the structure in your file.h (you can use typedef to create an alias)
typedef struct Books
{
char title[50];
int book_id;
} books;
then, you have to include your file.h in your file.c and declare your variable like this
#include "file.h"
int main()
{
books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
or like this if you didn't use typedef
#include "file.h"
int main()
{
struct Books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
Thank you all.
I read again what you said and found that the code above is now correct.
The error I report is with testing the following main.c
#include "structures.h"
#include "FunctionSet1.h"
void main() {
struct type_struct1 struct2;
struct2=function1();
}
in which structures.h is included again, thus causing the error. Removing the include eliminates the error.
I will now look into header guards to avoid such problems.
Thanks again.

C - unknown type name (global struct)

I have a file a.h which defines the structure:
typedef struct q_elem_s
{
def_task task;
struct q_elem_s *next;
} q_elem;
def_task is a structure in a second file b.h.
typedef struct task_s
{
int id;
int length;
} def_task;
Now my compiler says that def_task task inside q_elem_s is unknown?
a.c includes b.h. What is the problem then?
a.h should include b.h
Strange, I have another version of this code and it worked without
this.
When it worked without a.h including b.h, it probably did because a.c (or whatever main file) included b.h before a.h.

Resources