I am trying to create bunch of void methods and call them later in program.
I will demonstrate the code ahead to help better understand my issue.
.h file
static float sfloat;
namespace someNamespace
{
static void foo();
}
.cpp file
void someNamespace::foo(){cout<<sfloat<<endl}
above code is simpler version of class that I was working on.
I initialize sfloat in other .cpp file
otherFile.cpp
void initializeAndUseFoo(){sfloat = 5; someNamespace::foo();}
As far as my understanding goes, I expect foo to print out 5 but it prints out 0 instead.
This behavior occurs across all other static variables that I have as well(pointer included). It seemed that somehow the variables inside the function are never initialized as the value I assign.
However if I call out "sfloat" not through the function then I can call it out properly.(if I just print it out on console with just
cout<<"just print it not through the function : " <<sfloat<<endl;
then it is indeed 5
Thank you for reading.
A global static variable is static within one compilation unit. If you make another compilation unit, it will have a separate copy of that static variable.
This SO question explains what a compilation unit is in C++.
Since your variable is static and global in the same time, there will be a single instance of it in it's compilation unit. If you want to access that exact variable from another file, you will have to use the extern keyword. Without it, a new copy of that variable will be created in each compilation unit. You can find some information here, for example.
That's not a class, it's a namespace. static inside the namespace or at global scope gives methods and variables internal linkage. That means a copy of each will be available for each translation unit.
Because you modify (not initialize) sfloat in otherFile.cpp, only that version of the variable is modified. The original, initialized in .cpp file, retains the same value (which is the version printed by someNamespace::foo().
Related
In C++, I have been taught that a static linkage global variable is created when program starts and destroyed in the end of program. If the variable get destroyed in the end of the program (not file), I think there's definitely a way to use it in other files. I want to know how.
There are multiple meanings to static.
A variable declared at the file scope with static is visible only to functions in that file. You cannot use a static variable defined in one file from another file.
It sounds like you want a normal global variable. Just leave off the static.
"Local" variables, declared at at the function scope, have a default "auto" lifetime - their values persist only as long as the function executes, and once the functin returns, the value is gone. You can change this to live as long as the program with static.
If the variable is defined in a header, simply include the header and use it. If it's declared globally in a compilation module (i.e. .cpp file), then declare an extern version of it and use it. Note, this is not static which implies internal linkage which explicitly reduces the scope of the variable to a single compilation unit. This is global / external linkage.
E.g.
module1.cpp
int globalX = 5;
module2.h
extern int globalX;
module2.cpp
std::cout << globalX;
Been a while since I've done much C++, but I believe this should work.
Could someone tell me what's the purpose of declaring static functions outside classes? What's the difference between this 2? Are there any benefits for using static in this situation?
static void someRandomFunction();
int main()
{
someRandomFunction();
return 0;
}
and
void someRandomFunction();
int main()
{
someRandomFunction();
return 0;
}
At namespace scope, static gives a name internal linkage, meaning that it is only accessible within the translation unit that contains the definition. Without static, it has external linkage, and is accessible in any translation unit.
So you'd use static (or, alternatively, an unnamed namespace) when writing a function that's only intended for use within this unit; the internal linkage means that other units can define different functions with the same name without causing naming conflicts.
Non-static functions (and global names in general) are better declared in a header, to make sure that every translation unit that uses them gets the same declaration.
The static keyword on global functions or variables limits the visibility and linkage scope of the function or variable to the current translation unit.
That means that for a function, it can only be called from the current source file, and not from other source files.
A static function remains visible only in file scope. This is a C feature.
The recommended way to do it in C++ is using an anonymous namespace, as in:
namespace // no name, i.e. anonymous
{
void someRandomFunction();
}
int main()
{
someRandomFunction(); // visible only within this file.
return 0;
}
Note that the function body also has to be declared somewhere within the same file since the linker will not try to find it in other (external) translation units.
So void someRandomFunction(); is really a forward declaration for a function that is defined elsewhere in the same file (i.e. in the same translation unit).
If the function is actually called, you will get a linking error unless the function body is defined in the same file.
(The more pedantic technical term is actually not file but translation-unit since the body might be in an #includeed header do not in the actual file per-se. )
static void someRandomFunction();
This has to be used within same compilation unit (source file) and outside that compilation unit, not available for use.
Whereas, if you have
void someRandomFunction();
with one definition acrosss the program, the function can be used by any compilation unit globally across the program
Static methods and static functions are entirely different things.
Static methods are methods of a class instead of an instance (which you already know, as it seems).
Static functions, on the other hand, are function which are available only in the module they are defined in. They are not exported and cannot be put in a header file and used in another c file. This way you can write different functions sharing the same name, and also the compiler may optimize your code more thoroughly by inlining the function, knowing that no other file is dependant on it.
static tells the compiler not add the function to the symbol table for the object file. This effectively means that the linker is unable to find the function which in turn means you can only use the function directly in the current compilation unit. You can however call static functions from another compilation unit if this is done through a function pointer.
I would like to make an array of integers via the malloc method. I want this array to be global and be used anywhere in my program. I put code in a header file that looked like this:
static int *pieces;
Then I have a function that fills it with numbers that I want in there. The function is in a namespace and the namespace is implemented in its own .cpp file. However, I import the header file into main.c and call the function from the namespace that creates the array like:
pieces = malloc(sizeof(int) * 128);
But when I try to access numbers in the array in main (after calling the function that creates my array), it crashes and says that pieces wasn't initialized. But in the function I have I can create it and manipulate the numbers in it just fine. I was under the impression that by making pieces a static variable, whenever some function anywhere changes (or sets it) then that will affect the usage of the variable anywhere. Basically what I'm trying to say is why does pieces appear unset in main, even though I set it in a function that I called?
Static is a keyword with many meanings, and in this particular case, it means not global (paraphrasing)
It means that each .cpp file has its own copy of the variable. Thus, when you initialize in main.cpp, it is initialized ONLY in main.cpp. The other files have it still uninitialized.
First thing to fix this would be to remove the keyword static. That would cause the "Multiple definitions issue". To fix this you should define the variable in a .cpp file and just extern declare it in a header file.
Edit: You are just allocating memory to it, doesnt count as initialization. You need to initialize the memory to 0 after allocation.
You can use new int[128]() instead of your more verbose malloc syntax, and this would perform initialization as well? Or you could take the easy road (thats what its there for) and use std::vector
The key is this:
static int *pieces;
You said you put that in your header. This is not the way to export a symbol. Any file that includes the header will get its own static version of an uninitialised pointer called pieces.
Instead, you put this in your header:
extern int *pieces;
extern int init_pieces();
And in the source file, you do this:
static const size_t num_pieces = 128;
int *pieces = 0;
int init_pieces()
{
pieces = malloc( num_pieces * sizeof(int) );
return pieces != NULL;
}
Now when you include your header, your source file will know to get pieces from somewhere else, and will wait for the linker to work out where. I also suggested an 'init' function for the array. I did not put a 'release' function in, however.
Note this is all C, not C++. If you're using C++ you should really use new or better still, use a vector.
Also, when using statics in C++, be mindful of this: C++ static initialization order
In C++17 standard, you can use inline specifier instead of static. For variables this means every object unit will have a copy of the variable, but linker will choose only one of them.
Or, as stated on cppreference:
An inline function or inline variable (since C++17) has the following
properties:
1) There may be more than one definition of an inline
function or variable (since C++17) in the program as long as each
definition appears in a different translation unit and (for non-static
inline functions and variables (since C++17)) all definitions are
identical. For example, an inline function or an inline variable
(since C++17) may be defined in a header file that is #include'd in
multiple source files.
2) The definition of an inline function or
variable (since C++17) must be present in the translation unit where
it is accessed (not necessarily before the point of access).
3) An inline function or variable (since C++17) with external linkage (e.g.
not declared static) has the following additional properties:
1) It must be declared inline in every translation unit.
2) It has the same address in every translation unit.
Supported in (source):
MSVC since version 19.12 (VS 2017 15.5)
GCC 7
Clang 3.9
ICC 18.0
In this case, it means you can replace
static int *pieces;
with
inline int *pieces;
For high performance code on various architectures, you may want a malloc-y allocation rather than generic new. That is because you would wrap it with something like mymalloc() and then use architecture dependent functions, such as ones that implement the proper alignment to avoid cache misses and do other nifty things provided by the hardware manufacturer, such as IBM (Bluegene) or Intel (MIC). All of these optimized allocation routines have the malloc type framework.
I'm writing a game framework and I'm trying to generalize and encapsulate platform dependent code like the renderer so that it makes it a bit easier to port. I'm trying to accomplish this while still having a clean way of using the framework. I'm currently having a problem with static variables and namespaces...
// Renderer.h
namespace Renderer
{
static IRenderer* g_pRenderer = NULL;
static IRenderer* Get(void) { return g_pRenderer; }
static IRenderer* CreateD3DRenderer()
{
g_pRenderer = new RendererD3D(); // Derived from IRenderer
return g_pRenderer;
}
}
So in my main(), I can call CreateD3DRenderer() and it returns an instance just fine; g_pRenderer is holding its value since it's being created and returned within the scope of its function... However, Renderer::Get() returns NULL. Removing 'static' from the init of g_pRenderer causes clashes when used in other files.
What's going on?
First off, void in an argument list is only necessary in C. In C++, you'd just write Get().
As for the main question, static variables are restricted to the compilation unit. Since you put them in a header, this results in a separate variable being created for every compilation unit (i.e. every cpp file) where it is included. You get errors when you remove the static part because then you have multiple variables with the same name, leading to a linking error.
If you want a single variable to be shared between multiple files, you use extern. However, this is considered bad practice. You're better off refactoring so you don't need global variables like that.
You should keep all definitions of functions in .cpp files, instead of .h
What is happening is that when static is used in that fashion, the function or variable is restricted to that .cpp file, which means that g_pRenderer is different in each .cpp file. Multiple definition doesnt happen since each definition is restricted to one .cpp file.
You need to remove it to get your global pointer to work. You can keep the static on the getter function, but I would remove it. You should move the definition of the function and the global variable to a .cpp file and keep just a declaration of each in the .h. Declare the variable as extern.
static keyword keeps the scope of a global variable limited to that translation unit.
If I use static int x in a .h file and include that .h file every other file, won't they all belong to the same translation unit?
Then, won't x be visible everywhere?
So what is the role of static now?
Also, is there any use of static const int x ,where x is a global variable?
Aren't all const global variables static by default?
And is a const variable's scope limited to the TU even if it confined in a for loop in the file?
If you write
static const int x
in an .h file then every translation unit that #include-s this .h will have its own private variable x.
If you want to have 1 global variable visible to everyone you should write
extern const int x;
in the .h file and
const int x = ...;
in one of the .cpp files.
If you want to have a static const int visible to just one translation unit - don't mention it in the .h files at all.
If I use static int x in a .h file and include that .h file every
other file, won't they all belong to the same translation unit?
If you declare something as static (not inside a class, for class static keyword has a different semantic), that static variable cannot be seen outside its TU. So putting it in the header file will cause each TU including that header to have a different private copy of that static variable.
And is a const variable's scope limited to the TU even if it confined
in a for loop in the file?
NO. Even for a static const value, the scope is determined by it's declaration. So the scope will be limited by your for brackets.
you will end up will private copies of that variable per translation, which will result in bloat if you put it there. it would also make no sense to have to random copies all over the place. no it's not ok.
you can declare a const int in a namespace block; that's ok.
The observable difference for variables that are const qualified is that in the static version you will get one copy per translation unit and so address comparisons of two such copies may fail.
If you never use the address of your const variable any modern compiler should be able to just use the value and optimize the variable itself out. In such a case a static const-qualified variable is completely fine.
Basically, each source file together with all included header files is a single translation unit. So If you have a static variable in a header file then it will be unique in each source file (translation unit) the header file is included in.
"static global" doesn't make sense, they are in a way each other's opposites.
The term "global" is often misused to describe a variable declared outside any function at file scope. But rather, a global variable is one with external linkage, that can be accessed by any file in the project - hence global.
The opposite of external linkage is internal linkage, which means that a variable can only get accessed by the translation unit where it is declared. Translation unit meaning one .c file and all the headers included by it (recursively).
static is a guarantee that a variable gets internal linkage. Thus other translation will not be able to access it or declare extern variables referring to it.
What happens if you declare a static variable in a header file is that more than one translation unit will get a separate variable with that name. The code will compile fine, although clever linkers will notice this and give a linker error. These kind of linker errors are often non-descriptive and hard to track down.
This leads us to the following best practices:
Never declare any variables inside a header file, as this often creates subtle bugs and linker errors.
To prevent such bugs, always surround all header files with "header guards":
#ifndef MYHEADER_H
#define MYHEADER_H
/* contents of header */
#endif
All variables declared at file scope should be declared static, for the purpose of private encapsulation and to reduce namespace clutter. Similarly, extern should be avoided, as it leads to bad design and spaghetti programming.