local,static,register,extern and global

I want to know what is local,static,register,extern and global ?
please explain with examples.
I'm not sure about local and global (are those even C++ keywords?)

To keep my examples small I'm using pseudo-code and not real C++

static has several different meanings:

1) when used on local variables, it indicates the variable has a lifetime equal to the program's lifetime, and is not destroyed/reconstructed each call, but rather remembers its value between calls:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int increment()
{
  static int val = 0;
  ++val;
  return val;
}

int main(...)
{
  cout << increment() << endl;
  cout << increment() << endl;
  cout << increment() << endl;
  // outputs "1" "2" "3"
}


2) Similar to #1, When used on class member variables, it means there is 1 variable of that type shared for ALL objects of that class -- in other words the varialbe/object is basically global: created at program startup and destroyed on shutdown, but has class scope.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Myclass
{
static int v;
};

int main(...)
{
  Myclass a, b;
  a.v = 5;
  b.v = 4;

  if(a.v == 5)  //will fail -- 'MyClass::v' is 4

  MyClass::v = 10;  // legal syntax because v is static -- it doesn't need an instance of the class
}


3) Similar to #2... when used on class member functions it basically means that the function acts global, even though it's a member function. This means you cannot use the class's 'this' pointer in the function, nor can you access any member variables or member functions (unless those members are static themselves). However this also means you don't need an object instance to call the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Myclass
{
int no;
static int yes;
static void func()
{
  ++no;   // illegal, cannot access non-static members
  ++yes;  // legal... 'yes' is static
}
};

int main(..)
{
  Myclass::func();  // legal call -- don't need an object to call a static func

  Myclass a;
  a.func();    // alternative way to call it
}


4) Lastly (I think), when used on global functions/variables, it indicates that the function/variable has file scope and is not linked to other source files. This is weird because it pretty much means something completely different than the other meanings of 'static'.

Basically, static globals are invisible in other source files. This allows you to use the same global name in two seperate files (if they're both static) and they will not produce linker errors due to conflictions. This isn't a very practical thing to do though.

One of the more practical things to do with static globals is to avoid "function already defined" errors if you want to have a global function defined in a header file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// in a hdr.h
void func_a()  { }
static void func_b()  { }

void func_c();
static void func_d();

//---------------------------
// in file1.cpp:
#include "hdr.h"
void func_c() { }
static void func_d() { }

void file1()
{
  func_c();
  func_d();  // works just fine, func_d is defined in this file
}

int no;
static int yes;

//---------------------------
// in file2.cpp:
#include "hdr.h"

void file2()
{
  func_c();  // works fine -- func_c is defined in file1.cpp
  func_d();  // error -- func_d has no visible body (body in file1 can't be seen)
             //   because the function is static
}

int no;
static int yes;

//---------------------------
Linker error:

func_a is defined multiple times -- once in file1.cpp and again in file2.cpp.
however func_b doesn't have this problem because each of file1 and file2's version
of func_b is invisible to the other file.

'no' variable will also give errors because it has multiple bodies (declared multiple times
in global scope).  However 'yes' will be fine and will act like two seperate variables -- the
'yes' in file1 will be a different var than the 'yes' in file2.




'register' is not so complicated. It simply tells the compiler to try and keep the varialbe in a CPU register rather than to put it in RAM. There usually isn't much reason to use 'register', as minor optimizations like this are typically handled by the compiler automatically.

'volatile' is the exact opposite: A variable declared as volatile will be sure to be written to RAM every time it is modified. This makes it a good choice for variables key to inter-thread communication:

1
2
3
4
5
6
7
8
9
10
class myclass
{
  void threadclosed() { threadrunning = false;  }
  void waitforthread()
  {
    while(threadrunning)  sleep(1);
  }

  bool threadrunning;
};


This code might run into problems because as an optimization, the compiler might keep 'threadrunning' in a register rather than poll the actual variable every iteration of the loop. This means that it will keep sleeping even after threadrunning was set to false. This problem is solved by making threadrunning a volatile bool, which ensures the loop will poll the actual variable every time.


I'm fuzzy on 'extern' myself. I know how to use it for some things but I'll leave that open for someone more familiar with it.
Topic archived. No new replies allowed.