以前对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\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;
}

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

结果:

话说extern和static的更多相关文章

  1. 链接(extern、static关键词\头文件\静态库\共享库)

    原文链接:http://www.orlion.ga/781/ 一. 多目标文件的链接 假设有两个文件:stack.c: /* stack.c */ char stack[512]; int top = ...

  2. IOS的变量前加extern和static字段

    IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...

  3. 全局变量,extern和static以及命名空间的区别

    全局变量,extern和static以及命名空间的区别        全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...

  4. [C]控制外部变量访问权限的extern和static关键字

    一.extern 概述 编译器是由上至下编译源文件的,当遇到一些函数引用外部全局变量,而这个变量被定义在该函数声明主体的下方,又或者引用自其它的编译单元,这个情况就需要extern来向编译器表明此变量 ...

  5. C++中extern “C”含义及extern、static关键字浅析

    https://blog.csdn.net/bzhxuexi/article/details/31782445 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C ...

  6. iOS中的extern与static

    1.extern #import <Foundation/Foundation.h> extern NSString *DBDefaultName; @interface DataBase ...

  7. 关于extern和static关键字引出的一些关于作用域和链接属性和存储类型的问题

    在进入正题前我们必须了解一些概念: 标识符:标识符不仅仅代表着变量的名字,main()函数的main也是一个标识符,这点很重要. 存储类型:即变量的存储位置及其生存周期:静态区:分为两块 .date ...

  8. extern 和 static和 今天的一些代码,12-03

    这是关于标识符的链接属性的,链接属性只有三种:external, internal, none 改变规则: 3.1 文件作用域的变量和函数定义,即在所有 代码块和参数列表之外的标识符,使用static ...

  9. C语言关键字register、extern、static

    C语言中: 一.register变量 关键字regiter请求编译器尽可能的将变量存在CPU的寄存器中.有以下几点注意的地方. register变量必须是能被CPU寄存器所接受的类型,这通常意味着re ...

随机推荐

  1. Node.js Error: listen EADDRNOTAVAIL

    1 前言 nodejs部署在云服务器,外网用域名加端口访问不进来,但在服务器本地用127.0.0.1加端口可以访问,并且端口已经放开,然后只能排查配置.此文章仅作为记录使用. 如果端口和另一个的端口一 ...

  2. OCM_第二十天课程:Section9 —》Data Guard _ DATA GUARD 搭建/DATA GUARD 管理

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  3. java 持有对象 ListIterator用法

    package ch07; import java.io.*; import java.util.Iterator; import java.util.LinkedList; import java. ...

  4. CentOS6.8安装RabbitMQ

    1.安装erlang 安装依赖包: yum install xmlto gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel unixODBC ...

  5. Dockerfile中ENTRYPOINT 和 CMD的区别

    一.dockerfile中的 CMD 1.每个dockerfile中只能有一个CMD如果有多个那么只执行最后一个. 2.CMD 相当于启动docker时候后面添加的参数看,举个简单例子: docker ...

  6. k8s 关键字以及管理流程。

    一.流程图如下 二.用户通过kubectl提交需要运行的docker container(pod). 三.api server把请求存储在etcd里面. 四.scheduler(调度)扫描,分配机器. ...

  7. POJ1456 Supermarket 并查集

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1456 题意概括  一家超市,要卖出N种物品(每种物品各一个),每种物品都有一个卖出截止日期Di(在该 ...

  8. HDU3336 Count the string KMP 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - HDU3336 题意概括 给T组数据,每组数据给一个长度为n的字符串s.求字符串每个前缀出现的次数和,结果mo ...

  9. 020 $.each的使用

    在工作中见到这个知识点,不是特别懂,就查了查资料,顺便整理一下 1.定义与用法 each() 方法规定为每个匹配元素规定运行的函数. 提示:返回 false 可用于及早停止循环. 语法 $(selec ...

  10. hdu 2167 方格取数 【状压dp】(经典)

    <题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数 ...