C: initialising global constants with external linkage - c

I want to statically initialise a struct that will be visible from all files which include some header.
The actual intention is to run lists of functions specified at compile time, which is why I want to initialise statically. I'd like to put the lists where they belong, in the file in which they are declared or defined.
Contrived example:
general.h:
struct Widget { int (*a)(); };
foo.h:
int oof1(void);
int oof2(void);
foo.c:
#include "foo.h"
int oof1(void) { return 1; }
int oof2(void) { return 2; }
struct Widget foo_widgets[] = { {oof1}, {oof2} };
bar.c:
#include "foo.h"
#include "baz.h"
struct Widget *foo_widgets;
struct Widget *baz_widgets;
struct WidgetsContainer {
struct Widget *widget_list;
} wlists[] =
{
{ foo_widgets },
{ baz_widgets }
};
void usage(void) { ... ; process (wlists[i].widget_list); ... }
This obviously doesn't work because "the initialiser element is not constant" - This is because when the compiler is translating bar.c, it thinks it doesn't know the location of foo_widgets (or bar_widgets).
But since bar.c #includes foo.h anyway, it's always compiled alongside foo.c:
gcc foo.c baz.c bar.c
So I'm hoping there's a way of reflecting this in the source code.
I can't declare foo_widgets in foo.h, because then I wouldn't be able to initialise it without defining it multiple times (as foo.h is included in more than one file).
Inelegant workaround
foo.h:
...
Widget *get_foos(void) { return foo_widgets; }
bar.c:
...
struct Widget_lists {
struct Widget (*widget_list)();
} wlist[] =
{
{ get_foos },
{ get_bazes }
};
void usage(void) { ...; process(wlist[i].widget_list()); ... }
Is there a better way?

You want to have a global variable that you can reach anywhere ... To do so you have to declare it as an external variable in the appropriate header.
Here, it should be done as follows :
In foo.h :
/* ... */
int oof1(void);
int oof2(void);
extern int (*foo_widget)(void)[2];
In foo.c :
int (*foo_widget)(void)[2] = {{oof1}, {oof2}};
By doing so, when including "foo.h", the foo_widget variable will be known (and expected to be defined somewhere else - in foo.c here - ).
To be more precise ... Any piece of code that needs to make use of foo_widget must have the line extern int (*foo_widget)(void)[2]; somewhere, be it in an included header (the smarter way) or just a line at the beginning of the .c file.
Of course, if you cannot know in advance the number of widgets you can have, you are likely to need a dynamic data structure such as a linked list or a tree (ordered and balanced if possible ;) ) to store them. The extern variable is likely to be a regular pointer dynamically allocated when needed. But the definition line is still needed, so in this case you might have something like struct my_struct *pointer = NULL; in the appropriate source file.
Note : I took the freedom to replace your struct Widget with a common function pointer to get the initialization simpler.

Related

Why isn't this a valid method to create a default struct instance in C? [duplicate]

This question already has an answer here:
Why can't I assign values to global variables outside a function in C?
(1 answer)
Closed 1 year ago.
So suppose I have the following two files:
// main.h
struct Player {
int health;
int stamina;
};
// main.c
#include "main.h"
#include <stdio.h>
int main() {
struct Player newPlayer;
newPlayer.health = 100;
newPlayer.stamina = 100;
return 0;
}
This works fine.
Now suppose I have these two files:
// main.h
struct Player {
int health;
int stamina;
};
struct Player defaultPlayer;
defaultPlayer.health = 100; // error here
defaultPlayer.stamina = 100; // error here
// main.c
#include "main.h"
#include <stdio.h>
int main() {
struct Player newPlayer = defaultPlayer;
return 0;
}
The error in question is:
Unknown type name 'defaultPlayer'
[clang: unknown_typename]
My question is: Why can't I define a default struct in the .h file?
You cannot assign values to members at the file scope because only declarations and definitions are allowed on the scope level.
While defaultPlayer.health = 100 is an expression.
To set default values put it into struct initializer:
struct Player defaultPlayer = {
.health = 100,
.stamina = 100,
};
Moreover it may be a good idea to make it const.
You can make it an extern symbol. The defaultPlayer would only be declared in main.h and defined main.c.
// main.h
extern const struct Player defaultPlayer;
//main.c
const struct Player defaultPlayer = {
.health = 100,
.stamina = 100,
};
Cons: the compiler cannot inline values of members for translation units other than main.c.
Or use a static object in the header.
// main.h
static const struct Player defaultPlayer = {
.health = 100,
.stamina = 100,
};
Cons: compiler may complain about unused variables. What can be silenced by adding a dummy function:
static inline void dummy(void) { (void)&defaultPlayer; }
The third option is to make it a macro that expands to the compound literal.
#define defaultPlayer (const struct Player){ .health = 100, .stamina = 100 }
IMO, works the best.
A naive try:
A header defines the interface the object will offer to other objects. Therefore it should not contain any implementation detail.
Imagine you have the following files:
/* pretty_print.h */
// header guard
void pretty_print(char* str);
/* pretty_print.c */
#include <stdio.h>
#include "pretty_print.h"
void pretty_print(char* str) {
printf("%s", str);
}
#include "pretty_print.h"
int main() {
pretty_print("Hey there");
}
There will be two objects generated: main.o and pretty_print.o
None of which is yet executable. Neither does main.o contain any function pretty_print.
Linking both together will provide main.o the necessary pretty_print function (as well as do some more stuff).
Now assume there is some sort of data, let's say int x in the pretty_print.h .
As main.o included the header file, there will be such an x. However, pretty_print.o will have an x as well, as it includes pretty_print.h. So there will be two x and the compiler can't know which one to choose.
But I can declare the struct, I just can't change it's values
Yes you can, but you shouldn't declare instances in headers.
To answer, why you can't change it's values, remember there is a main function. When is this "global code" in your execution path? When is it intended to be run?
Please just fix...
You can always use struct initialization in the following way:
struct foo_t {
int x;
};
struct foo_t foo = { .x = 42 };
If you run in any further errors I assume you have to use the extern keyword with a pointer to a player-struct and initalize it with a default player in main

Declaring an extern struct template in header file for global use in c files

My goal is to declare and define a single structure template in my header file. I then wish to use this template to declare and define individual structures in my c files.
This is a rough example of what I'm aiming for:
header file
#include <bool.h>
extern struct options
{
extern bool aflag;
extern bool cflag;
extern bool dflag;
} option1;
...
c file
#include "header.h"
struct options option1;
void function(void)
{
option1.aflag = true;
option1.cflag = true;
option1.dflag = true;
}
...
I want this to result in the structure option1 being globally visible. The global contents should be aflag = true, cflag = true, and dflag = true.
When I say global, I mean that the contents aflag = true, cflag = true, and dflag = true (defined in another c file) should now be usable in yet a second c file if I wish. The only reference being the header file with the structure.
However, as I expected, this example contains multiple errors. I have only recently learned the basics of structures and am unsure of how to achieve exactly what I'm looking for, so it would be helpful if someone could explain how this effect can be achieved, possibly with code examples.
Thank you.
When you declare a structure you define a type.
If you want a struct to be globally visible then you need tp define a variable not a type.
So you can do something like this in your foo.h header file:
struct foo {
int bar;
double baz;
};
extern struct foo globally_visible_foo_yay;
And then in the foo.c file you want:
#include "foo.h"
struct foo globally_visible_foo_yay = {.bar = 42, .baz = 42.0};
And in some other C file you can then use the globally visible struct by including the header.

a good way of sharing data between modules using C

There are two C modules: A and B. They are indepentent from each other.
What is the best way to interchange data between them, if I want to keep them as much independent as possible?
I'll indicate you how to manage an integer, that is very simple! ... :)
An example may be the following. We have three files: a.c, b.c and b.h
The file a.c will manage an integer that is globally and statically allocated (statically to hide the variable to other C modules) by the b.c module that exposes the functions to manage that integer.
The file b.h contains the declaration of the functions the module b.c exposes.
The file a.c is:
#include "b.h"
int main(void)
{
setdata(8);
printf("%d\n",getdata());
return 0;
}
The file b.c may be:
#include "b.h"
static int data; /* Here static means data is hidden to other C modules */
int getdata(void)
{
return data;
}
void setdata(int val)
{
data=val;
}
The file b.h
#ifndef B_H__
#define B_H__
void setdata(int);
int getdata(void);
#endif
In C, you implement information hiding by declaring your persistent variables at "static". Outside a function, this means "only visible from this .c file"; inside a function, it means "local to this function, but persistent".
You then communicate between modules only by calling functions, passing values into them and getting return values from them.

Make a single definition from main.c to be available for a library at compile time

Lets say I have a main.c file
#include "library.h"
#define LIBRARY_VALUE 5
int main(void)
{
somefunction1();
return 0;
}
library.h
void somefunction1(void);
library.c
#include "library.h"
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
#endif
static unsigned char oneString[LIBRARY_VALUE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void)
{
printf("The Library Value is %d\n", LIBRARY_VALUE);
}
What I want to do here, is to be able to compile main.c and having LIBRARY_VALUE‘s value to be used as I defined right after the include in main.c.
How should I use GCC in order to achieve this?
I do need the value to be defined in main.c.
In case I have to change my code, I need a minimum working example code please. So I know clearly how to do this. Thanks.
In C there is no way for different .c files to share a common macro defined in one of the .c files. The tradition is to put it in a .h file, but you say this will not work for you.
You will need a type of "constructor" function that sets up your "static" information at run time. This constructor can be called directly by main.c, or indirectly by having main.c define an extern the library picks up.
I'll throw you some code, but I haven't tried to compile it... I'll leave that as an exercise for the student.
main.c
#include "library.h"
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
library.h
extern int const library_value;
void somefunction1(void);
library.c
#include <assert.h>
#include "library.h"
static unsigned char *oneString;
// destroy any memory from lib_init().
static void lib_clear(void)
{
if ( oneString )
{
free(oneString);
oneString = NULL;
}
}
// initialization - strop the static if the caller is to start it up.
static void lib_init( void )
{
if ( ! oneString ) // (defensive "if" to be sure)
{
assert( library_value > 0 );
oneString = (unsigned char*)malloc( library_value );
atexit( &lib_clear );
}
}
void somefunction1(void)
{
if ( ! oneString ) // if the main() is not calling an the constructor then
lib_init(); // // every method within the library must do so.
printf("The Library Value is %d\n", library_value);
}
The lib_init() and lib_clear() methods could be made externs with a lib_init( int size ) signature to take the size.
Your goal seems to have a single definition referenced multiple places.
There are a limited number of possibilities:
#define in .h
extern defined in main, or somewhere else outside of library.
extern defined in library.
Value passed by caller to library, perhaps an initialization call for the library.
Something defined before #include library.h that is picked up by library.h. I don't like this one.
As alfa says, make it a compile-time definition.
An example of a #define within library.h.
// library.h
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
void somefunction1(void);
#endif
Or, have main define a value defined by the caller and referenced by the library:
// library.h
extern int const library_value; // caller to define in main
void somefunction1(void); // function for caller
// main.c
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
The one I don't like is:
//main.c
#define LIBRARY_VALUE 5
#include "library.h"
//library.h
#ifdef LIBRARY_VALUE
int const library_value = LIBRARY_VALUE; // executable code in .h files is evil
#endif
Some of the reasons I dont' like this is that it is obscure and unconventional, if two or more callers of library.h define LIBRARY_VALUE you will, or at least should, get obscure link time errors. The same applies if LIBRARY_VALUE is not defined by an #include... library.c itself can not define a default value. No, I'd much rather call an initialization function for the library that accepts the constant.
The problem with the way you seem to want this to work, is that the constant gets used when the library is compiled -- you can't use one value when compiling the library and then compile a program with a different value and expect the library's code to magically change to use the new constant. You have some options when it comes to alternatives, though.
You could move the array into the program rather than the library, and give the library a pointer to it, and its size.
Or you could use a dynamically allocated array in the library, and add an initialization function to do the allocation (using the size provided by the program).
Or, you could ditch the library and just compile its code as part of the program -- then you can use a constant defined for the program as long as its done where the (previously) library code will see it.
Recommendation (assuming you want "myarray" visible outside the library):
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
extern unsigned char myarray[ARRAY_SIZE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
Otherwise, if you just want "somefunction1()" and the array size, then declare another function, "array_size ()":
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
int array_size (); // library.c will define "myarray" and it will
// define function array_size as "return ARRAY_SIZE;"
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
ALSO:
Please remember that "static" has two meanings:
1) Hides visibility of a variable or function name to file scope (the name is "invisible" outside of the source file)
2) allocates space for the object from static storage (instead of the heap (malloc/new) or stack (local variables)).
If you only want the "static storage" part; then you don't need the keyword "static". Just define your variable outside of a function, and you're set :).
Yet another issue is whether you want to make "ARRAY_SIZE" a compile time variable. If so, you should make sure it gets defined EXACTLY ONCE (when library.c is compiled), and is used IN ONLY ONE PLACE (library.c and library.c only). For example:
// library.c
#include "library.h"
#ifndef ARRAY_SIZE
#error ARRAY_SIZE IS UNDEFINED!
#else
static unsigned char myarray[ARRAY_SIZE];
int array_size ()
{
return ARRAY_SIZE;
}
#endif
...
What you are trying to do is not possible because library.c and main.c are compiled separately. You should compile library.c with "gcc -DLIBRARY_VALUE=5 ..." instead.

Hide struct definition in static library

I need to provide a C static library to the client and need to be able to make a struct definition unavailable. On top of that I need to be able to execute code before the main at library initialization using a global variable.
Here's my code:
private.h
#ifndef PRIVATE_H
#define PRIVATE_H
typedef struct TEST test;
#endif
private.c (this should end up in a static library)
#include "private.h"
#include <stdio.h>
struct TEST
{
TEST()
{
printf("Execute before main and have to be unavailable to the user.\n");
}
int a; // Can be modified by the user
int b; // Can be modified by the user
int c; // Can be modified by the user
} TEST;
main.c
test t;
int main( void )
{
t.a = 0;
t.b = 0;
t.c = 0;
return 0;
}
Obviously this code doesn't work... but show what I need to do... Anybody knows how to make this work? I google quite a bit but can't find an answer, any help would be greatly appreciated.
TIA!
If you're using gcc you can use the constructor attribute,
void runs_before_main(void) __attribute__((constructor))
{
...
}
From the gcc documentation
The constructor attribute causes the
function to be called automatically
be- fore execution enters main ().
Similarly, the destructor attribute
causes the function to be called
automatically after main () has
completed or exit () has been called.
Functions with these attributes are
useful for initializing data that will
be used implicitly during the
execution of the program.
You may provide an optional integer
priority to control the order in which
constructor and destructor functions
are run. A constructor with a smaller
priority number runs before a
constructor with a larger priority
number; the opposite relationship
holds for destructors. So, if you have
a constructor that allocates a
resource and a destructor that
deallocates the same resource, both
functions typically have the same
priority. The priorities for
constructor and destructor functions
are the same as those specified for
namespace-scope C++ objects
If you want to hide a struct from users, declare the struct in a header but define it in the c file, passing around pointers. As an example:
// foo.h
typedef struct private_foo foo;
foo * create_foo(void);
void free_foo(foo * f);
// foo.c
struct private_foo {
int i;
}
foo * create_foo(void){
foo * f = malloc(sizeof(*foo));
if (f) f->i = 1;
return f;
}
...
foo->i can then not be accessed outside foo.c.
If you want the client code to be able to use "t.a = ...", then you cannot hide the struct definition. What you want is called an opaque type, that will look something like this:
public.h:
struct foo;
set_a( struct foo *, int );
struct foo * new_foo(void);
main.c:
#include <public.h>
int main( void )
{
struct foo *k;
k = new_foo();
set_a( k, 5 );
}
The structure definition is only available to the library. If you do not make the library source code available, it is possible to completely hide it from the users of the library.
There is no portable way in C to ensure your code will run before main(). What I would do is just maintain an initialised flag in your library, set to false, and then refuse to do anything until your init function has been called.
As in:
static int initialised = 0;
int init (void) {
// do something.
initialised = 1;
return ERR_OK;
}
int all_other_functions (void) {
if (!init)
return ERR_NOT_INITED;
// do something.
return ERR_OK;
}

Resources