1

I have these three source files:

test.h

#ifndef __TESTH
#define __TESTH

    #ifdef __cplusplus
        #define EXTERNC extern "C"
    #else
        #define EXTERNC
    #endif

    typedef struct {
        uint8_t value;
    } my_struct;
    
    EXTERNC void initialise();
    EXTERNC void load(my_struct**);

#endif

test.cpp:

#include <cstdint>
#include "test.h"

my_struct test;

void initialise() {
    test.value = 200;
}

void load(my_struct** struct_ptr) {
    *struct_ptr = &test;
}

main.cpp:

#include <cstdint>
#include <iostream>
#include "test.h"

my_struct *test;

int main() {
    initialise();
    load(&test);
    
    while (true) {
        std::cout << test->value << std::endl;
    }
}

When I compile it, the linker gives me an error telling me that test has been defined multiple times (first defined in test.cpp).

Why? To me it seems like it doesn't leave the scope of test.cpp.

And when I remove the definition of test in main.cpp, it gives me an undefined error!

Thank you for taking the time out of your day to help me.

Gladuin
  • 13
  • 3
  • 1
    To make a global variable not leave the scope of test.cpp, you can do one of two things: `static my_struct test;` or `namespace { my_struct test; }`. – Eljay May 22 '22 at 17:43
  • It looks like `test` in main.cpp is supposed to be an entirely different `test` than the `test` in test.cpp. Is my understanding here correct? – Nathan Pierson May 22 '22 at 17:43
  • things defined at file level are globally visible, you have two things called test at file level. Either change the name or put 'static .... test' in the test.cpp file – pm100 May 22 '22 at 17:44
  • 1
    On an unrelated note, double leading underscores for symbol names are reserved for the compiler and standard library. You should not define such symbols yourself. See [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) – Some programmer dude May 22 '22 at 17:44
  • As for your problem, why do you define the two `test` variables as globals? Perhaps would make sense in the `test.cpp` file if you also made it `static`, but why in the `main.cpp` source file? – Some programmer dude May 22 '22 at 17:46
  • *"while variable is not defined anywhere else in the code"* -- this is not entirely accurate, is it? You do have a variable named `test` defined somewhere else in the code. From the question title, I would expect there to be no other variables named `test` even if you have reason to believe they are in different scopes. (The title does say "code", not "scope".) – JaMiT May 22 '22 at 17:50
  • 1
    Does this answer your question? [Multiple definitions error](https://stackoverflow.com/questions/21971350/multiple-definitions-error) – JaMiT May 22 '22 at 18:04
  • 1
    This doesn't address the question, but names that contain two consecutive underscores (`__TESTH`) and names that begin with an underscore followed by a capital letter are reserved for use by the implementation. Don't use them in your code. – Pete Becker May 22 '22 at 18:20
  • @NathanPierson test in main.cpp is supposed to point to test.cpp's instance of the struct – Gladuin May 22 '22 at 21:14
  • @Someprogrammerdude this is actually arduino code edited to be more of a general c++ question, hence why it's global in main.cpp – Gladuin May 22 '22 at 21:20
  • @JaMiT correct, I'll edit my post title also, that does answer my question, thank you! i accidentally marked as if it didn't, can i change that somehow? – Gladuin May 22 '22 at 21:20
  • I recommend you invest in [some good C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) to learn more about scopes and life-time. – Some programmer dude May 23 '22 at 05:05

1 Answers1

0

I think you would need to scope test.cpp's test variable to that file only, assuming your test pointer in main.cpp is different than test in test.cpp

namespace {
    my_struct test;
}

See here

P0W
  • 46,614
  • 9
  • 72
  • 119
  • thank you, this works great. i was assuming that putting a variable outside of any functions would keep it inside that files' scope only. – Gladuin May 22 '22 at 21:24
  • It's good to realize that to a certain extent, there is no such thing as a "file" except for your convenience as a human. When you compile the program, conceptualize all input files as concatenated together, the `#include`s literally replaced by the contents of the included file and _then_ the compiler goes to work. – CompuChip May 22 '22 at 21:36
  • However, here the two `test` symbols are in different *translation units* (what you get after concatenating the includes), that is why compilation works and linking fails. See also the *Linkage* section here https://en.cppreference.com/w/cpp/language/storage_duration – Sebastian May 23 '22 at 05:05