Search code examples
linker-errorsstatic-memberscompiler-explorer

Confusion about the linker error regarding static class members


I faced the unresolved symbol linker error regarding a static member of a class. I have found this and some other threads which learned me, that I have to declare an instance of the static member variable also outside of the class.

This is my code:

#include <stdint.h>

class GPIO_Port {
public:
    GPIO_Port(int PortNo)
    {
        mbUsedGpio |= (1 << PortNo);
    }

private:
    static uint16_t mbUsedGpio;
};

uint16_t GPIO_Port::mbUsedGpio;  // if missing - will produce the linker error

GPIO_Port PortA = GPIO_Port(1);
GPIO_Port PortB = GPIO_Port(2);

int main()
{
}

My questions are:

  • What is the reason for the extra declaration of the static member variable?
  • Why don't I get the error when I check the code in 'Compiler Explorer'?

This is the related test in 'Compiler Explorer' https://godbolt.org/z/En7oEaExb


Solution

  • (1) The reason compiler-explorer doesn't show the error is that by default it only compiles into an object file, and doesn't do linking. If you mark one of the appropriate checkboxes in the compiler pane:

    enter image description here

    You'd see the same link error: https://godbolt.org/z/E3e4debjY

    (2) The historic reason for the declaration/definition separation is C's separation of compilation and linkage. You declare a static data member as part of the class declaration, typically in a header. It isn't stored in the instances, and the class declaration was included in many translation units - so the linker (traditionally) was unable to make the decision on where to allocate storate for it. So, you have to communicate a single intended storage, by separately defining it in a single translation unit (c/cpp source file).

    Interestingly, for const int static members today you don't have to supply a separate definition. Here's some discussion of it if you're interested, but that seems beyond the scope of an SO answer.