Best practice to use extern struct or extern pointer to struct? - c

Say I have 3 files: file1.c, file2.c and globals.h. file1.c and file2.c both include globals.h. file1.c contains a struct that file2.c needs to use. Is it better to make the struct itself extern or create a pointer to the struct and make that pointer extern in globals.h?

If I understand correctly and your "a struct" is supposed to be a global object (which is a questionable design choice), then I'd do it like this:
foo.h:
typedef struct foo_struct
{
/* ... */
} foo;
extern foo the_foo;
foo.c: [If you like and if it makes sense, you can merge this into file1.c.]
#include "foo.h"
foo the_foo = { /* ... */ };
file1.c and file2.c:
#include "foo.h"
#include "global.h"
/* ... */

Related

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(){
}

C Some headers include each other

I can't solve next problem:
//foo.h
#ifndef FOO_H_
#define FOO_H_
#include "BAR.h"
#include "foos/foo_bazz.h"
typedef struct
{
...
} FOO;
// HERE I HAVE CALL `foo_baz(foo, bar);`
void
foo_bar(FOO *foo, BAR *bar);
#endif /* FOO_H_ */
//bar.h
#ifndef BAR_H_
#define BAR_H_
typedef struct
{
...
} BAR;
#endif /* BAR_H_ */
//foos/foo_bazz.h
#ifndef FOO_BAZZ_H_
#define FOO_BAZZ_H_
#include "FOO.h"
#include "BAR.h"
void
foo_baz(FOO *foo, BAR *bar);
#endif /* FOO_BAZZ_H_ */
so it makes error like this:
foos/foo_bazz.h: error: unknown type name ‘FOO’; did you mean ‘FOO_H_’?
16 | FOO *foo,
| ^~~~
| FOO_H_
I tried to remove #include "FOO.h" from foos/foo_bazz.h and add typedef struct FOO; or typedef struct FOO FOO; but it didn't make some changes...
Also i tried to make inverse - i declared function in FOO.h, but result is the same.
Help me please, thank you
Why do you want to include foo_bazz in foo.h?
It will fail for sure. The inclusion of the foo.h in foo_bazz.h will not declare the type as it is already protected by the guards.
It makes no sense. Simply include foo_bazz.h in your .c file where you will have function and data definition. IMO X-Y problem.
The problem is that the declaration:
void foo_baz(FOO *foo, BAR *bar);
is encountered before FOO is defined. You can solve that problem by reordering the code in foo.h thus:
#include "BAR.h"
typedef struct
{
...
} FOO;
#include "foos/foo_bazz.h"
void
foo_bar(FOO *foo, BAR *bar);
That said #0___________ 's solution makes more sense in most cases, including this, but it is worth understanding why/how the problem occurred rather than simply blindly fixing it.

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

Passing array of structures to a function in different file in C

I need to pass an array of structures defined in a file "file1.c" to a function, lets say "myFunc()", defined in another file "file2.c". The thing is that I don't know how to set the prototype of myFunc() in my header file "header.h" or in the function itself in my file2.c because the struct will only be defined in file1.c . Here is an example.
file1.c
#include "header.h"
#define dim 30
#define searchAgents 30
struct Wolf{
double pos[dim];
double fitness;
}Pack[searchAgents];
int main(){
myFunc(Pack); //not sure it's ok
return 0;
}
file2.c
#include "header.h"
void myFunc(struct Wolf Pack[]){ //I don't know how to set this argument
Pack[0].pos[0] = 1; //just an example
}
header.h
#ifndef HEADER_H_
#define HEADER_H_
void myFunc(struct Wolf); //I don't know how to set this prototype
#endif
I read about passing structures to functions but it's different when you have your function defined in another file. Thanks for your time.
header.h
#ifndef HEADER_H_
#define HEADER_H_
//Add all needed includes
#define dim 30
#define searchAgents 30
typedef struct Wolf{
double pos[dim];
double fitness;
}Pack; //Declaration
void myFunc(Pack *);
#endif
In main
#include "header.h"
int main(){
Pack packArray[searchAgents]; //Definition or initialization if you like
myFunc(packArray);
return 0;
}
file2.c
#include "header.h"
void myFunc(Pack *pack){ //just a pointer to Pack structure
pack[0].pos[0] = 1;
}
You can try making Pack[] as an extern type variable
extern keyword tells the compiler that the variable is define in some other .c file which is compiled along with this file with -o option in gcc compiler .
ex
extern Pack[10];

extern without type

If the syntax of extern is
extern <type> <name>;
how do I extern if I have an unnamed, single use struct:
struct {
char **plymouthThemes;
char *plymouthTheme;
} global;
I've tried
extern global;
without any type, and it doesn't work.
Or, do I have to name the struct?
You need to name your struct and put it in a .h file or included the definition by hand in every source file that uses global. Like this
///glob.h
struct GlobalStruct
{
///char** ...
///
};
///glob.cpp
#include "glob.h"
struct GlobalStruct global;
///someOtherFile.cpp
#include "glob.h"
extern struct GlobalStruct global;
If you do not want to name a struct there's common method:
--- global.h: (file with global struct definition):
#ifdef GLOBAL_HERE /* some macro, which defined in one file only*/
#define GLOBAL
#else
#define GLOBAL extern
#endif
GLOBAL struct {
char **plymouthThemes;
char *plymouthTheme;
} global;
---- file1.c (file where you want to have global allocated)
#define GLOBAL_HERE
#include "global.h"
---- file2.c (any oher file referencing to global)
#include "global.h"
The macro GLOBAL is conditionally defined so its usage will prepend a definition with "extern" everywhere except source where GLOBAL_HERE is defined. When you define GLOBAL_HERE then variable gets non-extern, so it will be allocated in output object of this source.
There's also short trick definition (which set in single .c file where you allocate globals):
#define extern
which cause preprocessor to remove extern (replace with empty string). But do not do it: redefining standard keywords is bad.
The idea is that you need to declare only one but still need to define the variable in each other file that uses it. The definition includes both the type (in your case a header define structure - which therefore need include) and the extern keyword to let know the compiler the declaration is in a different file.
here is my example
ext.h
struct mystruct{
int s,r;
};
ext1.c
#include "ext.h"
struct mystruct aaaa;
main(){
return 0;
}
ext2.c
#include "ext.h"
extern struct mystruct aaaa;
void foo(){
aaaa;
}
ext3.c
#include "ext.h"
extern struct mystruct aaaa;
void foo2(){
aaaa;
}

Resources