0

I have a header file where I have declared a structure and declared it as

static Test_t = TESTID;

Have multiple files in the project and files has multiple functions. And want to update these variables from different files and functions. So have tried to get the address of this static variable inside each function like

Test_t *info = &TESTID;

Update it as info-> ...

But the address of info are different in functions?
What could be the reason?

Mike
  • 4,041
  • 6
  • 20
  • 37
  • 1
    Don't declare variables in header files.That's the reason for your problems. In your case each C file has a different static variable. Remember that header files are textually included before the actual compilation. – Jabberwocky Apr 15 '20 at 10:42
  • 1
    You need to make the variable also `extern`, otherwise there is one copy per compilation unit that includes the header file. – Hristo Iliev Apr 15 '20 at 11:11
  • `static Test_t = TESTID;` doesn't look like it should compile – Colin Apr 15 '20 at 11:12
  • @Colin this is probably an implicit `int` declaration. – Jabberwocky Apr 15 '20 at 11:18

2 Answers2

4

One of the main reasons of using static in the first place, is to make a variable local to the scope where it is declared. If you declare it at file scope (outside all functions), then it is local to the translation unit where it was declared. A translation unit means a .c file and all .h files that the .c file includes.

Meaning that if you have a static variable in foo.h, then #include "foo.h" from foo.c and bar.c, then you will end up with two different local copies of that variable: one inside the translation unit foo.h + foo.c, and another inside the translation unit foo.h + bar.c.

The solution is to never declare any variables inside header files. In addition to strange hiccups like the one described above, you can also run into various linker errors.

One sensible solution is to have the static Test_t test = TESTID; inside test.c only. Then make setter and getter functions from test.h that other functions will use to access the variable.

The struct declaration can be placed in test.h if the getters return copies or const pointers and other files should be allowed to access members directly. Or rather, that's fine for simpler stuff, but not recommended for more complex ADTs that should use proper private encapsulation.

(The only drawback with such a design is that it isn't thread-safe unless you implement thread safety inside the setter/getters, but that's another story.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

You basically want something like this:

Header.h

...
extern int thevariable;   // this only declares that thevariable exists
                          // somewhere else
...

file1.c

#include "Header.h"
...
int thevariable;     // declare the variable in one and only in one place
...
thevariable = 123;

file2.c

#include "Header.h"
...
thevariable = foo;  // refers to thevariable declared in file1.c

file3.c

#include "Header.h"
...
bar = thevariable;  // refers to thevariable declared in file1.c

For this you don't need (and don't want) static variables.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 1
    Re “// declare the variable in one and only in one place”: The `extern int thevariable;` in Header.h **declares** the identifier in multiple places. You mean to **define** the identifier and its object in only one place. – Eric Postpischil Apr 15 '20 at 11:30
  • 1
    I wouldn't really recommend using read/write `extern` variables for any purpose. Leads to spaghetti design in 99% of all use cases. There are some exceptions, like memory-mapped hardware register maps, but no exceptions in everyday application layer programming. – Lundin Apr 15 '20 at 11:41
  • @Lundin the OP put the xilinx tag, and in that context it may make more sense than in everyday application layer programming – Jabberwocky Apr 15 '20 at 11:52
  • Haven't used it myself, but as long as the code is written in C and not some HDL, it shouldn't be that much different from microcontroller programming. Which in turn means that extern should only be used in rare special cases. – Lundin Apr 15 '20 at 14:37