Search code examples
carmkeil

C Programming Error: undefined symbol to a struct (Keil error L6218E)


I am using Keil MDK ARM to develop a project. However, when I am trying to build my code, the software tool throws the ERROR: L6218E : Undefined symbol Bit (referred from main.o). Where Bit is a struct that I am using to store boolean values. For eg:

In variable.h file

struct
{
    unsigned bPowerONStatus : 1;
    unsigned bTimerONStatus : 1;
} extern Bit;

In main.c file:

#include variable.h

int main()
{
    while(1)
    {
        ReadTimerStatus();
        if(Bit.bPowerONStatus)
        {
            // System is ON
        }
        else
        {
            // System if OFF
        }
    }
}

In PowerChecker.c file

#include variable.h

void ReadTimerStatus(void)
{
    if(Bit.bTimerONStatus)
    {
        Bit.bPowerONStatus = 1;
    }
    else
    {
        Bit.bPowerONStatus = 0;
    }
}

What am I doing wrong here? What is the correct method of defining a struct, that will be used in multiple source files?


Solution

  • Declaring a variable at file scope with the keyword extern, but with no initializer declares the variable to have external linkage, but does not define the variable. There needs to be a definition of the variable elsewhere in your program.

    In the case of your Bit variable, it has been declared with an anonymous struct type that has no type alias, so there is no way to use the same type when defining the variable. In order to fix that you need to either define the struct type with a tag, or define the struct type within a typedef declaration, or you can do both.

    It is more conventional to put the storage class specifier such as extern at the front of the declaration.

    In variable.h:

    struct StatusBits
    {
        unsigned bPowerONStatus : 1;
        unsigned bTimerONStatus : 1;
    };
    
    extern struct StatusBits Bits;
    

    In only one C file, e.g. main.c or variable.c:

    #include "variable.h"
    
    struct StatusBits Bits;
    

    Note that the struct StatusBits Bits; above has external linkage and has no initializer, but has not been declared extern, so it is a tentative definition of the Bits variable. Unless overridden by a definition of the same variable with an initializer, it will behave as if it has been initialized with {0}.