桜、抹茶、白、日記

名古屋市在住のC++使いのcoderの日記だったもの。

C/C++言語のstatic変数

激しく勘違いしていたようなので、調査。

// common.h
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED

static	int g_val1	= 1;

#endif
// ClassA.h
#ifndef CLASSA_H_INCLUDED
#define CLASSA_H_INCLUDED
#include <stdio.h>

static int g_val2 = 2;
extern int g_val3;

class ClassA {
public:
  ClassA() : m_val5( 5 ) {}
  ~ClassA() {}
  void Dump();
protected:
  static int m_val4;
  int m_val5;
};
#endif
// ClassA.cpp
#include "ClassA.h"
#include "common.h"

int g_val3 = 3;
int ClassA::m_val4 = 4;

void ClassA::Dump() {
  printf( "g_val1=0x%08p, g_val2=0x%08p, g_val3=0x%08p, m_val4=0x%08p, m_val5=0x%08p\n",
          &g_val1, &g_val2, &g_val3, &m_val4, &m_val5 );
}
// ClassAB.h
#ifndef CLASSAB_H_INCLUDED
#define CLASSAB_H_INCLUDED
#include "ClassA.h"

class ClassAB : public ClassA {
public:
  void DumpB();
};
// ClassAB.cpp
#include "ClassAB.h"
#include "common.h"
void ClassAB::DumpB() {
  printf( "g_val1=0x%08p, g_val2=0x%08p, g_val3=0x%08p, m_val4=0x%08p, m_val5=0x%08p\n",
          &g_val1, &g_val2, &g_val3, &m_val4, &m_val5 );
}
// ClassAC.h
#ifndef CLASSAC_H_INCLUDED
#define CLASSAC_H_INCLUDED
#include "ClassA.h"

class ClassAC : public ClassA {
public:
  void DumpC();
};
// ClassAC.cpp
#include "ClassAC.h"
#include "common.h"
void ClassAC::DumpC() {
  printf( "g_val1=0x%08p, g_val2=0x%08p, g_val3=0x%08p, m_val4=0x%08p, m_val5=0x%08p\n",
          &g_val1, &g_val2, &g_val3, &m_val4, &m_val5 );
}
// main.cpp
#include <stdio.h>
#include "ClassAB.h"
#include "ClassAC.h"
#include "ClassD.h"

int main(int argc, char* argv[]) {
  ClassA  a1;
  ClassA  a2;
  ClassAB ab1;
  ClassAB ab2;
  ClassAC ac1;
  ClassAC ac2;
  ClassD  d1;
  ClassD  d2;

  printf( "g_val1=0x%08p, g_val2=0x%08p, g_val3=0x%08p\n",
          &g_val1, &g_val2, &g_val3 );
  a1.Dump();
  a2.Dump();
  ab1.DumpB();
  ab2.DumpB();
  ac1.DumpC();
  ac2.DumpC();
  d1.Dump();
  d2.Dump();
  return 0;
}
    1. g_val1 は、ヘッダファイルに定義されたstatic変数で、複数のCPPファイルからインクルードされている。
    2. g_val2 は、クラス定義のヘッダファイルに定義されたstatic変数で、複数のCPPファイルからインクルードされている。
    3. g_val3 は、CPPファイルに定義されたグローバル変数で、extern宣言されている。
    4. m_val4 は、クラスのstaticなメンバ変数。
    5. m_val5 は、クラスのメンバ変数。

結果

g_val1=0x00418004, g_val2=0x00418000, g_val3=0x00418014
g_val1=0x00418010, g_val2=0x0041800C, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF54
g_val1=0x00418010, g_val2=0x0041800C, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF48
g_val1=0x00418024, g_val2=0x00418020, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF3C
g_val1=0x00418024, g_val2=0x00418020, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF30
g_val1=0x00418030, g_val2=0x0041802C, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF24
g_val1=0x00418030, g_val2=0x0041802C, g_val3=0x00418014, m_val4=0x00418018, m_val5=0x0012FF18
g_val1=0x00418038
g_val1=0x00418038
    1. g_val1 と g_val2 は、オブジェクトファイル(*.obj/*.o)単位で一意となる。
    2. g_val3 はプロセス内で一意となる。
    3. m_val4 はプロセス内で一意となる。

勘違いをしていたのは、1番目でstatic付けときゃプロセス内で一意だろと思っていたorz
関数についても今度調べよう。