话说extern和static

Posted tp-16b

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了话说extern和static相关的知识,希望对你有一定的参考价值。

以前对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
" );
     printf("f.c : a=%d
", ++*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的主要内容,如果未能解决你的问题,请参考以下文章

iOS 中 const static extern 关键字总结

static和extern使用 /static和const联合使用

extern和static关键字

auto, extern, register, static

static和extern理解

[原创] static, extern关键字的作用域,存储类型示例