C++ static extern file scope linkage

 
regarding static/extern, some stuff diff between c and c++. 
 
################################### 
####   static local variable   #### 
################################### 
 
static mem life cycle - once you declare it, it will exist until the program ends, as opposed to automatic mem life cycle where a variable is terminated once it reaches the end of the scope. 
 
 
---------------------------------//  main.cpp 
#include <iostream> 
#include "ken.cpp" 
using namespace std; 
 
int main() 
{                                     // static  |  non-static 
  cout << getsta(9) << endl;          // 109     |  109 
  cout << getsta(200) << endl;        // 309     |  300 
  return 0; 

-------------------------------- 
--------------------------------//  ken.cpp 
int getsta(int x){ 
  static int val = 100;         // "static" 
  val = val + x; 
  return val; 

-------------------------------- 
 
static variables are guaranteed to get initialized to 0(zero) while non-static variables are not. (hense you should initialize them whereever possible.) 
 
NOTE:  in C++, mem allocation for static variables happens when the declaration part is reached, but in C, mem alloc for static var happens at the beginning of the program execution. this means, the below code will be ok with C++ while illegal in C. 
 
----------------------------------------------------------- 
void func(int x){ 
static int val = x;   // illegal in C,  legal in C++ 

----------------------------------------------------------- 
 
 
 
 
################################## 
###   static global variable   ###  (to be distinguished from static "local" variable) 
################################## 
 
declaring a global variable with "static" keyword will restrict the variable to "file scope" (not program/global scope, not block scope.) 
 
study the next section. 
 
 
################################################## 
###   internal linkage  VS  external linkage   ### 
################################################## 
 
internal/external linkage has to be understood along with the concept of program(global) scope, file scope, block scope. 
 
global variables with static keyword will restrict the access from other files. (internal linkage) 
 
non-static global variables can be accessed from other files via "extern" specifier. (external linkage) 
# notice we are talking about "global" variables. i.e. variables that are outside any function definition. 
 
using extern to refer to a static global variable from other file will not work. see the BAD example section below. 
 
as shown below, to access static global var from other file, kinda like accessing encapsulated private var of a class, you need to implement some functions. generally speaking, a choice between using extern everywhere and using static global var with manipulator functions, the latter is preferred. 
 
 
###  static global var & extern  example 
 
 
----------------------------// test.h 
void setval(int); 
int getbar(); 
----------------------------// test.cpp 
#include "test.h" 
 
int foo = 100;              // program scope 
static int bar;             // file scope 
void setval(int x){ 
foo = foo + x; 
bar = bar + x; 

int getbar(){ 
    return bar; 

----------------------------// main.cpp 
#include <iostream> 
#include "test.h" 
                            // don't include "test.cpp" here because linker will link the variables. 
using namespace std; 
 
int main() 

    extern int foo; 
foo = foo * 2;             // 200; 
 
extern int bar;            // this will not compile. undefined reference to 'bar' 
 
setval(100);               // foo is 300, bar is 100; 
 
    cout << foo << endl;       // 300 
cout << getbar() << endl;  // 100  
 
return 0; 

----------------------------- 
 
===>  run  $ g++ -o ext main.cpp test.cpp     # this will link variables between files. 
           $ ext 
 
 
####  BETTER example on extern usage 
 
normally, the way we use extern is we put the extern declaration in a header file, and all the other files just refer to it, where one of the file actually defines it. 
 
-------------------- // header.h 
extern int foo; 
void some_func(); 
... 
 
-------------------- // src1.cpp 
#include "header.h" 
 
int foo;             // this has to be a global var, i.e. external linkage.  don't define this inside a func. 
... 
... 
 
-------------------- // src2.cpp 
#include "header.h" 
 
void some_func(){ 
   foo = 123; 

-------------------- 
 
 
 
####  BAD example 
 
in the below example, there will be two separate static global file-scope variables, one for each of foo.cpp and main.cpp 
 
-------------------------   // foo.h 
static int foo; 
void update_foo(int); 
int getfoo(); 
 
-------------------------   // foo.cpp 
#include "foo.h" 
 
extern int foo;             // in fact, this line does not mean anything, you can remove it. 
                            // once you included "foo.h" it declared static int foo in this file scope. 
void update_foo(int x){ 
  foo = foo + x; 

int getfoo(){ 
  return foo; 

 
-------------------------   // main.cpp 
#include "foo.h" 
#include <iostream> 
using namespace std; 
 
int main() 

  { 
    int local_foo = 100; 
    extern int foo; 
    foo = 123; 
  } 
  { 
    int local_foo; 
    local_foo += 100; 
    cout << local_foo << endl;  // 100 
 
    extern int foo; 
    foo = foo + 123;            // 246 
  } 
 
  cout << foo << endl;          // 246 
  cout << getfoo() << endl;     // 0 
 
  foo = foo + 1;                // 247 
  update_foo(111); 
 
  cout << foo << endl;          // 247 
  cout << getfoo() << endl;     // 111 
 
  return 0; 

 
------------------------ 
 
 
NOTE: 
also, there is no guarantee on the initialization order when you have multiple static variables. (except in the same translation unit, which is essentially the same source file, initialization happens in the order of declaration). therefore, dont construct the initialization of static global variables definition depending on other static global variables. 
 
 
 
 
(ref) 
http://stackoverflow.com/questions/10422034/when-to-use-extern-in-c 
http://stackoverflow.com/questions/14027317/what-is-the-difference-between-file-scope-and-program-scope 
http://oshiete.goo.ne.jp/qa/3670390.html 
http://www.learncpp.com/cpp-tutorial/43-file-scope-and-the-static-keyword/ 
http://forums.codeguru.com/showthread.php?157531-Difference-between-External-Linkage-and-internal-Linkage 
http://okuyama.mt.tama.hosei.ac.jp/unix/C/slide82.html 
 
 
 
 
 
 
############################ 
###   static function    ### 
############################ 
 
this is a function version of a static global variable. "static" keyword will make the function internal linkage, only accessble within the same source file. this means you cannot declare a function prototype in a header file. 
 
you use it when you want to define a func that shouldn't be accessed externally. 
 
---------------------------- stafunc.h 
void somefunc(); 
 
---------------------------- stafunc.cpp 
#include "stafunc.h" 
 
static void sta_func(); 
 
void somefunc(){ 
 
   ... 
   ... 
   sta_func();             // legal 
   ... 
   ... 

 
static void sta_func(){ 
   ... 
   ... 
   ... 

 
---------------------------- main.cpp 
#include "stafunc.h" 
 
int main() 
{                            // cannot call sta_func() directly, only thru somefunc() 
somefunc(); 
return 0; 

 
---------------------------- 
 
 
simple enough. 
 
 
 
################################# 
###   static member variable  ###    C++ 
################################# 
 
a static global variable defined within a class. 
 
---------------------------------- // stamem.h 
class CFoo 

 public: 
  void set(int); 
  int get(); 
 private: 
  static int bar; 
}; 
 
---------------------------------- // stamem.cpp 
#include "stamem.h" 
 
int CFoo::bar = 123;   // must define static member var outside the class def 
                       // initialization is optional. if no explicit init val supplied, then it becomes zero. 
                       // notice there is no "static" qualifier when defining. 
                       // 'static' may not be used when defining (as opposed to declaring) a static data member 
 
void CFoo::set(int x) 

  CFoo::bar = x; 
  //  bar = x;            // these will work alternatively 
  //  this->bar = x; 

 
int CFoo::get() 

  return CFoo::bar; 

 
---------------------------------- // main.cpp 
#include "stamem.h" 
#include <iostream> 
using namespace std; 
 
int main() 

 
  CFoo cf1, cf2; 
 
  cout << cf1.get() << endl;  // 123 
 
  cf1.set(456); 
  cf2.set(321); 
 
  cout << cf1.get() << endl;  // 321 
  cout << cf2.get() << endl;  // 321 
 
  return 0; 

 
---------------------------------- 
 
=======>   in the above example, if you make bar "public" static member variable, then you can access it without instantiating any class object of CFoo. 
 
e.g.   // this is not always a good use. 
 
---------------------------------- // stamem.h 
class CFoo 

 public: 
  static int bar;                  // you cannot initialize here 
  static const int baz = 123;      // if static 'const' then initialization allowed 
}; 
 
---------------------------------- // main.cpp 
#include "stamem.h" 
#include <iostream> 
using namespace std; 
 
int CFoo::bar = 777;   // this is a definition, which you can do, and will have to need to do, regardless of private|public. 
 
int main() 

CFoo::bar = 666;   // this you can do if it's public. 
                       // notice how you never instantiated the class but still can access the var. 
 
    cout << CFoo:bar << endl;   // 666 
 
CFoo cf; 
 
cout << cf.bar << endl;     // 666 
 
return 0; 

---------------------------------- 
 
 
################################## 
###   static member function   ###   C++ 
################################## 
 
- just like static member variable, static member function exist before the class gets instantiated. 
- because of this nature, static member function cannot access non-static member variables which can only exist after an actual class instantiation. 
- similarly, static member function cannot call non-static member function. technically non-static member function exist without class instantiation but since non-static member functions most likely access non-static member variables, we just ban static member function call non-static member function. 
- also, no "this" pointer cos static member func does not exist per instance. 
 
------------------------------------------------  // smf.h 
class CFoo 

   public: 
static int multiply(int& x){ return x *= 2;} 
}; 
------------------------------------------------  // main.cpp 
#include <iostream> 
#include "smf.h" 
using namespace std; 
 
int main() 

int num = 7; 
cout << CFoo::multiply(num) << endl;        //  14 
 
    CFoo cf; 
    cout << cf.multiply(num) << endl;           //  28 
 
return 0; 

------------------------------------------------ 
 
 
==========>  notice in the above example, if it's just only static member function, you are better off using namespace instead. 
 
------------------------------------------------  // main.cpp 
#include <iostream> 
using namespace std; 
 
namespace CFoo 

int multiply(int& x){ return x *= 2;}      // no need to make it static 

 
int main() 

    int num = 7; 
    cout << CFoo::multiply(num) << endl;        //  14 
 
    return 0; 

 
------------------------------------------------ 
 
==========>  notice how it's exactly the same but simpler. 
 
- if defining a static member function outside the class def, then do NOT put 'static' keyword. (this rule is the same for static mem var) 
 
e.g. 
--------------------------------------------- 
class CFoo 

public: 
static int multiply(int&); 

 
int CFoo::multiple(int& x) 

return x *= 2; 

--------------------------------------------

  1. 2014-05-08 01:53:34 |
  2. Category : cpp
  3. Page View:

Google Ads