1. 程式人生 > >話說extern和static

話說extern和static

自動 關於 變量覆蓋 call stdio.h c++的函數 ble 相關 定義

以前對extern、static的一些東西一直模棱兩可。今天好好來梳理了一番。。

static關鍵字

被static修飾的變量或函數稱之為靜態成員、函數。
存儲位置:static修飾的變量存放在靜態區(全局區)。通常有以下特點:

  • 修飾的變量只能在本源文件中訪問
  • 存放在此的變量在程序結束後由os自動釋放,生存周期隨程序
  • 僅能在編譯時期定義初始化一次. 以後操作都是在上次操作結果基礎上進行
  • 若是未初始化的靜態變量,os將默認為其賦值為0或者空字符

靜態局部變量與靜態全局變量不同的一點:

  • 雖然靜態局部變量在函數調用結束後仍然存在,但其他函數不能引用它

全局變量

定義在函數體外部的變量稱之為全局變量。

存儲位置:同樣存放在靜態區中。
特點:

  • 和上面static修飾的變量有相似的4個特點
  • 造成和局部變量的名字空間汙染,和局部變量同名將被局部變量覆蓋

與靜態變量的區別:

  • 全局變量可以被其他源文件(利用extern關鍵字)所訪問和修改

關於extern

作用:將被修飾變量聲明為外部變量

  • 聲明的變量可以訪問其它源文件的變量(前提是這個變量的具有外部鏈接屬性)
  • 同樣也可用來修飾函數聲明,以此調用其他源文件的定義的函數
  • 指示C或者C++函數的調用規範
    比如在C++中調用C庫函數,就需要在C++程序中用extern “C”聲明要引用的函數。這是給鏈接器用的,告訴鏈接器在鏈接的時候用C函數規範來鏈接。主要原因是C++和C程序編譯完成後在目標代碼中命名規則不同。
    例子: C++程序調用C語言函數 f()
//f.c

#include <stdio.h>
void f(int* a )
 {   
     printf("f.c : this is test\n" );
     printf("f.c : a=%d\n", ++*a);
 }
//main.cpp

#include <iostream>
using namespace std;
extern "C" void f( int*);
int main( )
{
     int a = 10;
     f(&a);
     cout<<"now"<<a<<endl;
    return 0;
}

若是反過來讓C語言調用C++函數,又該怎麽辦?

  1. 若只是簡單的調用C++的函數、重載函數時。將要調用的函數封裝即可
//C++ Code
#include <iostream>
using namespace std;
void f(int i)
{
    cout<<"f:i= "<<i<<endl;
}
void f(double d)
{
    cout<<"f:d= "<<d<<endl;
}
extern "C" void f_i(int i)
{
    f(i);
}
extern "C" void f_d(double d)
{
    f(d);
}
//C  Code
#include <stdio.h>
int main( )
 {
    f_i(10);
    f_d(10.111);
    return 0;
 }
  1. 若想要訪問C++代碼中的類對象。 此時就需要將整個類都封裝起來,對外提供C形式接口,和C++相關方法封裝在自定義的結構中

stu.h:

#ifndef __STU_H_
#define __STU_H_

typedef struct C_Stu C_Stu;
#ifdef __cplusplus
extern "C" {
#endif //__cpluscplus

    C_Stu* getInstance(void);   
    void releaseInstance( C_Stu** pp);
    void Call_Stu_func(C_Stu* p);
#ifdef __cplusplus
};
#endif //__cpluscplus
#endif //__STU_H_

C Code:

//C Code
#include <stdio.h>
#include "stu.h"

int main( )
 {  
    C_Stu* p = getInstance();
    Call_Stu_func(p);
    releaseInstance(&p);
 }

C++ Code:

//
#include <iostream>
using namespace std;

class Stu
{   
public:
    Stu()  {cout<<"Stu()"<<endl;}

    virtual void func()
    {  cout<<"virtual func"<<endl; }

    ~Stu() { cout<<"~Stu()"<<endl; }
};

#ifdef __cplusplus
extern "C" {
#endif //__cpluscplus
    typedef struct C_Stu{
        Stu s;
    }C_Stu;
    C_Stu* getInstance(void)
    {
        return new C_Stu;
    }
    void releaseInstance(C_Stu** pp)
    {
        delete *pp;
        *pp = NULL;
    }

    void Call_Stu_func(C_Stu* p)
    {
        p->s.func();
    }
#ifdef __cplusplus
};
#endif //__cpluscplus

結果:
技術分享圖片

話說extern和static