1

Not an emergency because the code still works, I'm mainly just curious.

I'm using raylib to make an RPG. I wrote a function that changes the displayed rotational sprite depending on the last direction the player moved. If you're unfamiliar with raylib, textures are a variable type which must be initialized with the function LoadTexture(const char *fileName). This is taken care of at program start by another function I wrote. For some reason, g++ is warning me that these variables are unused, even though they clearly are, due to the fact that the sprite is being rendered.

This is my declaration, in draw.h:

// Sprite variables
static Texture pUp; // Player facing up
static Texture pDown; // Player facing down
static Texture pLeft; // Player facing left
static Texture pRight; // Player facing right

I use a function PSetSprite(Dir pDir) which takes the current direction of the player as an argument and returns the correct rotational sprite.

Texture PSetSprite(Dir pDir) {
    static Texture pSprite = pDown;
    
    switch (pDir) {
        case UP:
            pSprite = pUp;
        break;
        
        case DOWN:
            pSprite = pDown;
        break;

        case LEFT:
            pSprite = pLeft;
        break;

        case RIGHT:
            pSprite = pRight;
        break;

        case UP_LEFT:
            pSprite = pLeft;
        break;

        case UP_RIGHT:
            pSprite = pRight;
        break;

        case DOWN_LEFT:
            pSprite = pLeft;
        break;

        case DOWN_RIGHT:
            pSprite = pRight;
        break;

        default:
        break;
    }
    return pSprite;
}

This is then passed to the player object with player.Draw(const Texture pSprite) and drawn to the screen. Deleting the variables obviously breaks my program, so what gives?

For those who asked, I am using version 12.2.0 of g++, and the specific error is "'pUp' defined but not used," x4 for each rotational sprite.

user17732522
  • 53,019
  • 2
  • 56
  • 105
WidePirate
  • 13
  • 3
  • 1
    Please [Edit] your post and tell us 1) your compiler and version, 2) copy/paste THE EXACT WARNING MESSAGE – paulsm4 Oct 17 '22 at 01:02
  • 1
    Using 'static' in a header file that is included into multiple source files is bad practice... Each object file will have its own private copy of those variables... (something you don't want.) Ditch the "static" and let the linker "marry-up" the multiple definitions from each object file into a single instance in the executable. Better yet, use "extern" in the header file and then define the instance in the source file where its use makes most sense... – Fe2O3 Oct 17 '22 at 01:03
  • This doesn't address the question, but you could eliminate some redundancy by restructuring that `switch` a bit: `switch(pDir) { case LEFT: case UP_LEFT: case DOWN_LEFT: pSprite = pLeft; break; /* et cetera */ }`. Yes, you can have multiple `case` labels that all lead to the same code. – Pete Becker Oct 17 '22 at 12:42

1 Answers1

3

The static keyword has different meanings depending on where it is used. Marking a variable at namespace scope as static (in contrast to block or class scope) gives it internal linkage, meaning that there will be a different variable of the same name and type in each translation unit including the declaration (i.e. each .cpp file including the header).

So the compiler is probably warning you that you are not using the variables in some translation unit where you also include the header but do not access them. Since each translation unit has an independent set of these variables, the compiler is correct to warn you that you are not using those instances of the variables.

If these variables are only supposed to be used in one translation unit, then they shouldn't be declared in a header shared with other translation units, but instead either in the .cpp directly or a separate header specific to that .cpp.

If the variables are intended to be accessed from multiple translation units, then they cannot be declared static. Instead of static the keyword inline can be used, which will give them external linkage so that they are the same variables in each translation unit, and at the same time the inline keyword allows the definitions of the variables to be included in multiple translation units (usually, without inline, you would need to declare them in the header with extern and then define them in only one translation unit), assuming that each definition is identical (e.g. included from the same header).

user17732522
  • 53,019
  • 2
  • 56
  • 105