以前写程序是,基本不管static和extern,一个工程文件也只有一个c文件。今天尝试用多个文件来写,自然就涉及到这两个关键词的使用,自己查了些资料,并且做了些实验,总结如下。

extern的用法

  • 可以扩展外部变量的作用域

如果在程序中某个地方定义了一个外部变量, 那么使用extern就可以扩展它的作用域。

举个栗子

 #include <iostream>

 using namespace std;
void fun(); int main()
{
extern int t; //将外部变量t的作用域拓展到从此处开始
fun();
cout << "t=" << t << endl;
return ;
} int t;
void fun()
{
t = ;
}

输出为

如果没有extern那句,主函数在执行到  cout << "t=" << t << endl  这句时,就不知道 t 是啥玩意。

但是要说明一点, 即使没有extern那句, fun() 函数也能顺利执行。

栗子:

 #include <iostream>

 using namespace std;
void fun(); int main()
{
// extern int t;
fun();
return ;
} int t = ;
void fun()
{
t += ;
cout << "hhh" << t << endl;
}

输出为

这是因为int t = 3 这句的作用域已经包含了fun()函数了。

  • 将外部变量的作用域拓展到其它文件

当你想在一个工程里用多个文件来写整个大程序,那么你在一个文件里定义了一个全局变量(外部变量), 不作声明的话,另一个文件是找不到这个变量的, 不像写在一个文件里那么简单。

这时就可以用extern来搞事了。其实这一点完全可以类比上一个作用,也就是说明extern不仅可以在一个文件里扩展作用域,在整个工程里都是可以的。

栗子:

 //main.c文件
1 #include <iostream> using namespace std;
void fun(); int t;
int main()
{
t = ;
fun();
cout << "t=" << t << endl;
}
//另一个.c文件
1 #include <iostream> using namespace std; extern int t;
void fun()
{
t += ;
}

输出

有必要说明一下,extern声明的必须得是外部变量,即定义在函数外面的变量, 要是你把第一个点的程序里面int t 写在子函数内部, 就会报错。第二点的也不能写在子函数里面。

/***************************分割线***********************/

static的用法

  • 阻止extern来扩展作用域

比如上面第一点中如果在int t 的前面加上static,那么extern不起作用了,就会报错。第二点也是这样。通常一个大工程会分给好多人一起写,如果一个人确定自己这个文件里的这个变量不会被其它文件使用,又不想被其它文件误用, 就加个static,起到隔离的作用。

  • 使某个局部变量在函数调用结束后保留原值

我们知道在一个函数里定义的变量,会在函数调用结束后被抹去,就像做梦一样,什么都没了。但是如果在函数里的某个变量前加一个static, 它的值就不会消失,好比你下次做梦还能接着上次的做。。。

举个栗子

 #include <iostream>

 using namespace std;
void fun(); int main()
{
fun();
fun();
fun();
} void fun()
{
static int t = ;
t++;
cout << t << endl;
}

输出

如果没有static,就会输出3个2。

也就是说static int t = 1; 这句话只会执行一遍,即初始化t 只有一遍。之后再到这里,它会直接跳过。

但是有人会说,这个不就和写一个大全局变量的用法重复了吗。确实,如果你在main函数前面直接定义一个全局变量int t; 实现效果是一样的

代码为

 #include <iostream>

 using namespace std;
void fun();
int t = ;
int main()
{
fun();
fun();
fun();
} void fun()
{
t++;
cout<< t << endl;
}

输出一样。

但是,两种做法其实并不一样,要是用static来写,那么只是把t 的生存期变长了,作用域并不会改变。也就是说,t 这个变量虽然在函数调用结束后,其值并不会消失,但是并不能在函数外面使用它。

它只能在函数里产生作用,在函数外面根本不知道有这个东西,甚至也可以定义一个t 的变量,而且并不会产生冲突。好比说,你梦里面干的事只能在你梦里干,就算你每次做梦都接着上次的做,然而现实生活中别人是不知道你做了啥梦。

栗子

 #include <iostream>

 using namespace std;
void fun(); int main()
{
int t = ;
fun();
cout << t << endl;
fun();
t++;
fun();
cout << t << endl;
} void fun()
{
static int t = ;
t++;
cout<< t << endl;
}

输出为

此时就像正常没有static 来处理t 一样,二者不会产生冲突。很神奇。

在自己瞎搞的过程中,我还发现一个现象。当你把刚刚那个代码中main 函数里的 int t = 100; 拿到main 函数外面,当成全局变量, 输出是一样的。

不仅如此,你把它写成全局变量后,即使再把子函数里的static去掉, 输出还是一样的。

这就说明了,一个大全局变量遇到子函数里定义的长得一样的小变量,大全局变量并不会影响小变量,读者可以自己试试。

我想可以这样理解这种情况,当你定义了一个大全局变量后,全局都可以使用,但是要是你在子函数中(不是main函数)也定义了一个相同的变量,无论你是否用static,子函数就按子函数定义的来搞,子函数结束,并不会影响你的大全局变量。

static和extern的用法小结的更多相关文章

  1. 《OOC》笔记(1)——C语言const、static和extern的用法

    <OOC>笔记(1)——C语言const.static和extern的用法 C语言中const关键字用法不少,我只喜欢两种用法.一是用于修饰函数形参,二是用于修饰全局变量和局部变量. 用c ...

  2. C++中extern关键字用法小结

    总结C++中关于extern关键字的用法. 1.变量的生明和定义中 C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译.为了将程序分为许多文件,则需要在文件中共享代码 ...

  3. 命名空间 extern的用法 static全局变量

    std是标准库中的命名空间: 关于extern的用法可以参考文献http://blog.163.com/sunjinxia%40126/blog/static/94984879201312145021 ...

  4. C++ typedef用法小结 (※不能不看※)

    C++ typedef用法小结 (※不能不看※) 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不 ...

  5. typedef用法小结

    typedef用法小结- - 注意:本文转自网络,版权归原作者所有. typedef typedef用法小结- - 这两天在看程序的时候,发现很多地方都用到typedef,在结构体定义,还有一些数组等 ...

  6. 16-static和extern关键字2-对变量的作用

    上一讲介绍了static和extern对函数的作用,static用来定义一个内部函数,不允许其他文件访问:extern用来定义和声明一个外部函数,允许其他文件访问.static和extern对变量也有 ...

  7. extern "c"用法解析

    转自: extern "c"用法解析 - 简书 引言 C++保留了一部分过程式语言的特点,因而它可以定义不属于任何类的全局变量和函数.但是,C++毕竟是一种面向对象的程序设计语言, ...

  8. extern "C" 用法解析

    extern "c"用法解析 作者 作者Jason Ding ,链接http://www.jianshu.com/p/5d2eeeb93590 引言 C++保留了一部分过程式语言的 ...

  9. 转载 浅谈C/C++中的static和extern关键字

    浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T   static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...

随机推荐

  1. [再寄小读者之数学篇](2014-07-27 $H^{-1}$ 中的有界集与弱收敛极限)

    设 $H^{-1}$ 是 $H^1_0$ 的对偶空间, 定义域为 $[0,1]$. 试证: (1) $\sed{h\sin (2\pi hx);\ h>0}$ 在 $H^{-1}$ 中有界; ( ...

  2. [译]Ocelot - Middleware Injection and Overrides

    原文 使用这个特性的时候要小心点. 可以如下一样提供一些中间件用以覆盖默认的中间件: var configuration = new OcelotPipelineConfiguration { Pre ...

  3. lnmp.org 安装环境的,root权限都没法删除网站文件夹,问题解决-转

    rm -rf删除网站目录时出现rm: cannot remove `.user.ini': Operation not permitted rm -rf删除网站目录时出现rm: cannot remo ...

  4. 25)django-form使用

    目录 1)django form作用 2)django form使用 一:django form 作用 django form有两个作用:一是用户输入数据验证:二是生成html 1)用户输入数据验证, ...

  5. Python--subprocess

    本节内容 os与commands模块 subprocess模块 subprocess.Popen类 总结 我们几乎可以在任何操作系统上通过命令行指令与操作系统进行交互,比如Linux平台下的shell ...

  6. Vue项目中,要保证某个部分的高度,应该怎么设置

    .icons overflow: hidden height: padding-bottom: % background: green

  7. 网络流24题——分配问题 luogu 4014

    题目链接:这里 本题是一个典型的费用流问题,可以作为费用流建图模板使用 首先看到,每个人只能做一件工作,每件工作只能做一次,一个人做某件工作有一定的收益 那么我们建立一个超级源点st和超级终点ed,然 ...

  8. 倒影问题(reflect:below)

    这个例子灵感来源于实现一个登录框下方的倒影: .box { width: 300px; height: 200px; border: 1px solid #1f637b; -webkit-box-re ...

  9. 论文阅读笔记四十四:RetinaNet:Focal Loss for Dense Object Detection(ICCV2017)

    论文原址:https://arxiv.org/abs/1708.02002 github代码:https://github.com/fizyr/keras-retinanet 摘要 目前,具有较高准确 ...

  10. scrapy_redis 相关: 将 jobdir 保存的爬虫进度转移到 Redis

    0.参考 Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误 1.说明 Scrapy 设置 jobdir,停止爬虫后,保存文件目录 ...