c++struct

Multiple Definitions of Variables with Structs


I've started working with structs and am having difficulty getting my head around splitting them up into .h and .cpp files. I understand that .h are usually used for declarations, whereas .cpp are used for definitions. The issue I've run into is I can't work out how to define the standard variables for two separate structs when these variables have the same names.

I think my issue is that the three variables for each struct are not being associated inside them (error 1). I tried taking these variables out of the .cpp files but then I get the issue that the variables within void Reset() were not declared within that scope.

What I am trying to achieve is having these variables within the struct with default values. The Reset() function, when called, will reset these values.

I'm running from Konsole with this: g++ -o main cpu.cpp main.cpp && ./main

Error 1

/usr/bin/ld: /tmp/ccwb32XV.o:(.bss+0x3): multiple definition of `PS'; /tmp/ccY9ydGx.o:(.data+0x3): first defined here
collect2: error: ld returned 1 exit status

Error 2

cpu.cpp:9:5: error: ‘PC’ was not declared in this scope
    9 |     PC = 0xFFFC;

cpu.h

#include <cstdint>

struct CPU
{
    std::uint16_t PC;
    std::uint8_t SP;
    std::uint8_t PS;

    void Reset();
};

cpu.cpp

#include "cpu.h"

std::uint16_t PC = 0x1234;
std::uint8_t SP = 0x56;
std::uint8_t PS = 0b10101010;

void Reset()
{
    PC = 0xFFFC;
    SP = 0xFF;
    PS = 0b00010000;
}

ppu.h

#include <cstdint>

struct PPU
{
    std::uint16_t X;
    std::uint8_t Y;
    std::uint8_t PS;

    void Reset();
    void PrintSomething();
};

ppu.cpp

#include <cstdint>
#include <iostream>
#include "ppu.h"
    
std::uint16_t X = 0x1010;
std::uint8_t Y = 0x99;
std::uint8_t PS = 0b11001100;

void Reset()
{
    PC = 0xAABC;
    SP = 0x02;
    PS = 0b00000110;
}
    
void PrintSomething()
{
    std::cout << "Printing something!" << std::endl;
}

main.cpp

#include <iostream>
#include "cpu.h"
#include "ppu.h"

int main()
{

    CPU cpu;
    PPU ppu;

    std::cout << "Hello, World!" << std::endl;
}

Solution

  • You are setting up your .cpp files the wrong way. You do not need to define non-static data members separately at all (only static data members, which you don't have). You do need to define member functions, like Reset(), but to do that correctly you need to fully qualify the struct name in the definition.

    Also, don't forget to put header guards in each .h file. And, you need to compile and link every .cpp file.

    Try this instead:

    g++ -o main cpu.cpp ppu.cpp main.cpp && ./main

    cpu.h

    #ifndef CPU_H
    #define CPU_H
    
    #include <cstdint>
    
    struct CPU
    {
        std::uint16_t PC = 0x1234;
        std::uint8_t SP = 0x56;
        std::uint8_t PS = 0b10101010;
    
        void Reset();
    };
    
    #endif
    

    cpu.cpp

    #include "cpu.h"
    
    void CPU::Reset()
    {
        PC = 0xFFFC;
        SP = 0xFF;
        PS = 0b00010000;
    }
    

    ppu.h

    #ifndef PPU_H
    #define PPU_H
    
    #include <cstdint>
    
    struct PPU
    {
        std::uint16_t X = 0x1010;
        std::uint8_t Y = 0x99;
        std::uint8_t PS = 0b11001100;
    
        void Reset();
        void PrintSomething();
    };
    
    #endif
    

    ppu.cpp

    #include <iostream>
    #include "ppu.h"
    
    void PPU::Reset()
    {
        X = 0x1010;
        Y = 0x99;
        PS = 0b11001100;
    }
        
    void PPU::PrintSomething()
    {
        std::cout << "Printing something!" << std::endl;
    }
    

    main.cpp

    #include <iostream>
    #include "cpu.h"
    #include "ppu.h"
    
    int main()
    {
        CPU cpu;
        PPU ppu;
    
        std::cout << "Hello, World!" << std::endl;
    }