Reputation: 387
Say, there is a proc.h which defines an array like
proc.h:
struct proc
{
char p_stat;
char p_flags;
int p_pid;
} proc[100];
And there are another 5 .c files including this header file. I did not see any of such .c files allocate the memory for this array. I think it's linker that allocates the memory for it. However, what appears in the header file should be just a declaration. How could a declaration causes the memory allocation? I thought only definition will cause the memory allocation.
Thanks,
Upvotes: 1
Views: 797
Reputation: 141554
As Morten Jensen noted, it is the same as doing:
typdef struct proc
{
// ...
} proc_t;
proc_t proc[100];
which is a definition of proc (not just a declaration). However this is probably a mistake. If this header is included in more than one translation unit, then it is undefined behaviour.
(I am posting this answer because all of the other answers so far say that it creates multiple copies of proc
, however that is wrong!)
It's undefined behaviour to have two (or more) definitions of an externally-visible variable.
If the intent is to have a single variable visible from multiple units, then proc_t proc[100];
needs to be replaced with the declaration:
extern proc_t proc[100];
and then exactly one unit does the definition proc_t proc[100]
.
If the intent is for all units to have separate copies of proc
, then replace with this definition:
static proc_t proc[100];
In both cases, proc
has what is called static storage duration. This means that the memory is allocated during program startup.
Upvotes: 1
Reputation: 5936
Say, there is a proc.h which defines an array like
proc.h:
struct proc { char p_stat; char p_flags; int p_pid; } proc[100];
The code above actually not only defines the data structure struct proc
, it also declares/allocates an array of them for each file including the header.
A widely used idiom is to define the data structure with a typedef, like so:
typedef struct
{
char p_stat;
char p_flags;
int p_pid;
} proc_t;
or just plain old defining the structure without the typedef:
struct
{
char p_stat;
char p_flags;
int p_pid;
} proc_t;
and then in the c-file matching the header, you'll instantiate your array of structs:
proc_t proc[100]; // if you've typedef'd the struct
struct proc_t proc[100]; // if you haven't typedef'd
and then in all the c-files including the header, wanting access to this global struct, you'll declare the variable extern. That way, all the c-files will share access to a single data structure.
I prefer to typedef a structure in a single header and encapsulate it by only accessing/manipulating instantiations of that data structures through function calls (objects passed by address), but that is a matter of personal taste and whatevs.
Upvotes: 3
Reputation: 2122
'header' files are included (become part of) a C file. You have declared and defined the array in your header file and then included that declaration into your five C files, so the space gets allocated 5 times. What you want to do is make the proc
array an extern
declaration in the header file, and then copy the exact same declaration (without the extern
) in one of your C files.
Or, you can accomplish much the same thing with macros, like so:
// foo.h
#ifndef MAIN
/*
* this declaration is extern for everybody except the
* MAIN module, (typically main.c) which defines
* the macro MAIN -- this ensures that all C files see the same
* structure definition, but space is allocated exactly once.
*/
extern struct proc {
#else
struct proc {
#endif
…
} proc[100];
in one of your C files, (e.g. main), you do this:
// main.c
#define MAIN
// when you include foo.h, the 'extern' will be left out, and space will be allocated
#include "foo.h"
in your other C files, you just do this:
// other.c
#include "foo.h"
This will cause space for the array to be allocated once (in main.o) and the other .o files will contain external references to proc[] which will be resolved by the linker.
Upvotes: 2
Reputation: 726569
I did not see any of such .c files allocate the memory for this array.
Actually, they all do: the declaration and the definition are copied verbatim into each translation unit that includes the header, so each translation unit gets its own definition of the proc[100]
array.
If you try linking the results of translation together, you should see a redefinition error produced by the linker, unless the actual header declares proc
static.
Of course the proper way of creating proc[100]
would be to declare it extern
in the header, and provide a definition in one of the .c
files.
Upvotes: 2
Reputation: 22241
The include
directive does nothing more than insert the included file into the file which includes it. In other words, all .c
files declare the structure separately, and declare (allocate memory) for the variable proc
. They all define memory for it separately. If all of them are later compiled together, I have no idea how can this possible work properly.
Upvotes: 2