Search code examples
cstructheader-filesextern

Use of struct from ".h" file


Say I have a header file file which contains a struct.

Struct aa 
{
    int a;
    int b;
};

In a.c file I include that header file and I do

struct aa first;

and then use first.a and first.b to make changes.

In b.c file I include that header file and I do

struct aa first;

and then use first.a and first.b to make changes.

Can I do whatever I did in b.c? How is linkage done? Does it overwrite the values? How does it work?

Or should I use extern anywhere ?


Solution

  • If you write struct aa first; in a function,

    // a.c
    #include "your_header.h"
    
    void foo(void)
    {
        struct aa first;
        first.a = 18;
        first.b = 19;
        ...
    }
    
    
    // b.c
    #include "your_header.h"
    
    void bar(void)
    {
        struct aa first;
        first.a = 21;
        first.b = 22;
        ...
    }
    

    then the variable is a local variable of foo and bar respectively, they happen to have the same name, but are not the same variable. So the initialization of first in bar does not affect in any way the variable first in foo.

    If you however want a global variable so that the different compile units (meaning different .c files) like a.c and b.c can access to, then you need to declare the variable as extern in the header and define it in either a.c or b.c.

    // your_header.h
    #ifndef YOURHEADER_H
    #define YOURHEADER_H
    
    struct aa {
        int a;
        int b;
    };
    
    // the "extern" tells the compiler that the
    // variable might be defined somewhere else,
    // it it's not in the current compile unit,
    // it won't give you an error.
    extern struct first;
    
    #endif
    
    
    // a.c
    #include "your_header.h"
    
    // a.c defines in this compile unit the global
    // variable. This information is important for the linker as well
    struct first;
    
    void foo(void)
    {
        first.a = 10;
        first.b = 11;
    }
    
    
    //b.c
    
    #include "your_header.h"
    
    void bar(void)
    {
        first.a = 100;
        first.b = 200;
    }
    

    Now when you compile a.c: gcc a.c -c -o a.o, the compiler knows from the header file that first is a global variable that may be defined in another compile unit. In this case it is defined in a.c itself.

    Now when you compile b.c: gcc b.c -c -o b.o, the compiler knows from the header file that first is a global variable that may be defined in another compile unit. It is not defined in b.c, so the compiler will let the linker deal with this.

    When you link your program: gcc a.o b.o othermodules.o -o myprogram, the linker will know in which object file the variable first was defined and will create the correct offsets for when the program access this variable.

    In this case, if you do this in main.

    #include "your_header.h"
    #include "other_headers.h"
    
    int main(void)
    {
        foo();
        bar();
    }
    

    then bar will override the values of first.a and first.b that were set in foo, because first is a global variable.