-1

I am using STM32F103 and and Keil for the Compiler. Here is my summary code: There is a header file like abc.h and abc file has a static variable. abc.h is like that:

static uint8 a;

And there is a function in another header file which named abcd.h and that changes the a' s value. abcd.h header file is like that.

include "abc.h"

void foo()
{
    a = 0x0A;
}

My issue is that: When I call the "foo" fuction in main "a" is turn to zero even if I assign the "a" variable to 0x0A in "foo()" function. By the way, If I define the "a" variable with extern and the problem does not occured. I mean "a" is get 0x0A value.

Is there anyone the help me why does this problem occur.

  • 1
    You have two different objects with different scopes using the same identifier. Try `printf("adress of object identified with a: %p\n", &a);` in a few locations in your code where any identifier `a` is in scope. Using `extern` is the right direction to generate a single object. – pmg Mar 02 '20 at 08:25
  • 1
    Does this answer your question? [What is the difference between static and extern in C?](https://stackoverflow.com/questions/3684450/what-is-the-difference-between-static-and-extern-in-c) – Sander De Dycker Mar 02 '20 at 08:25
  • I do not want to initialize variable as extern because when initialize a variable as extern. It is turn to a global variable and I do not want it. I am looking forward to another solution. – alptekin karabacak Mar 02 '20 at 08:30
  • 2
    @alptekinkarabacak If the same variable needs to modified by code in multiple C files, then that variable is global. A variable can't be both global and not global. – unwind Mar 02 '20 at 08:39
  • 2
    @alptekinkarabacak : I assume by "global", you mean "external linkage" ? If you want to be able to access the same variable from different compilation units, you *need* external linkage. – Sander De Dycker Mar 02 '20 at 08:41
  • 1. do not define data in the header files. 2. give us real code not something which does not even compile. make sure that the code in your question reproduces the problem. At the moment this question cannot be answered – 0___________ Mar 02 '20 at 08:52
  • Ok, thank you so much I understand the issue. I have two more questions. 1) I do not know, is there any negative effect of extern values (like wastes memory)? 2) Is that reasonable, write get() function for every include variable, like: uint8_t get_a() { return a; } – alptekin karabacak Mar 02 '20 at 09:15

1 Answers1

1

Some rules of thumb:

  • Never declare global variables. (extern ones)
  • Never declare variables inside header files.

static variables are per definition not global, but could be "file scope" - that is, visible to the file they are declared inside. Or more accurately, visible inside the translation unit they are declared inside, a translation unit meaning a specific .c file and all the headers that .c file includes.

So if you declare a static variable in a header, which is included by two different .c files, then you end up with multiple local copies of the variable. If you are lucky, you get a linker error, but the linker may as well attempt some internal "name mangling". The very meaning of static is to prevent access to the variable by other files.

The best solution to this is to use setter/getter functions:

// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H

uint8_t get_a (void);
void set_a (uint8_t n);

#endif

-

// abc.c

#include "abc.h"

static uint8_t a;

uint8_t get_a (void) 
{ 
  return a; 
}

void set_a (uint8_t n) 
{ 
  a = n; 
}

That is how you should be doing in the vast majority of cases. Using extern should be avoided, but for the rare cases when you have to use it, then use it like this:

// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H

extern uint8_t a;

#endif

-

// abc.c
#include "abc.h"

uint8_t a;
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Oh, thank you so much I was thinking about this and write one more question about that. – alptekin karabacak Mar 02 '20 at 09:10
  • 1
    @lundin "never declare" - never define I think. `extern .....` in header files are OK – 0___________ Mar 02 '20 at 10:00
  • @P__J__ It's the last resort. It's somewhat ok to do for `const` variables and also ok to do for hardware register memory maps. Other than that... you'd need some pretty special real-time requirements to justify "extern-spaghetti". Most often the presence of `extern` is simply caused by fishy design. – Lundin Mar 02 '20 at 11:56