zoukankan      html  css  js  c++  java
  • 话说extern和static

    以前对extern、static的一些东西一直模棱两可。今天好好来梳理了一番。。

    static关键字

    被static修饰的变量或函数称之为静态成员、函数。
    存储位置:static修饰的变量存放在静态区(全局区)。通常有以下特点:

    • 修饰的变量只能在本源文件中访问
    • 存放在此的变量在程序结束后由os自动释放,生存周期随程序
    • 仅能在编译时期定义初始化一次. 以后操作都是在上次操作结果基础上进行
    • 若是未初始化的静态变量,os将默认为其赋值为0或者空字符

    静态局部变量与静态全局变量不同的一点:

    • 虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用它

    全局变量

    定义在函数体外部的变量称之为全局变量。
    存储位置:同样存放在静态区中。
    特点:

    • 和上面static修饰的变量有相似的几个特点
    • 造成和局部变量的名字空间污染,和局部变量同名将被局部变量覆盖

    与静态变量的区别:

    • 全局变量可以被其他源文件(利用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;
     }
    

    2. ** 若想要访问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
    

    结果:

  • 相关阅读:
    负载均衡原理与实践详解 第十六篇 负载均衡网络设计 把负载均衡当作二层交换机还是三层路由器
    谈谈我对技术发展的一点感悟
    解析索引中数据列顺序的选择问题
    构建高性能.NET应用之配置高可用IIS服务器第四篇 IIS常见问题之:工作进程回收机制(上)
    关注分离的艺术(The Art of Separation of Concerns)
    如何修改.net framework
    [WPF Documents 之旅]System.Windows.Documents下的Class Diagram
    [转] 依赖注入&控制反转 oC 容器和Dependency Injection 模式(中文版)
    [WPF疑难]如何禁用窗口上的关闭按钮
    关于书写技术探讨性邮件的一点小小的建议
  • 原文地址:https://www.cnblogs.com/tp-16b/p/9379300.html
Copyright © 2011-2022 走看看