概述

static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。

但是对于c语言初学者,static由于使用灵活,并不容易掌握。本文就static在c语言中的应用进行总结,供参考使用。错漏之处,请不吝指正。

最后一节加入了c++面向对象中static的使用特性,当作拓展阅读。

变量

1. 局部变量

普通局部变量是再熟悉不过的变量了,在任何一个函数内部定义的变量(不加static修饰符)都属于这个范畴。编译器一般不对普通局部变量进行初始化,也就是说它的值在初始时是不确定的,除非对其显式赋值。

普通局部变量存储于进程栈空间,使用完毕会立即释放

静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。

变量在全局数据区分配内存空间;编译器自动对其初始化
其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束

小程序体会一下静态局部变量的威力:

#include<iostream>
using namespace std;void fun()
{int n = 10;cout << "n=" << n << endl;n++;cout << "n=" << n << endl;
}void fun_static(void)
{static int n = 10;cout << "n=" << n << endl;n++;cout << "n=" << n << endl;
}int main(void)
{cout << "第一次调用fun" << endl;fun();cout << "第二次调用fun" << endl;fun();cout << "第一次调用fun_static" << endl;fun_static();cout << "第二次调用fun_static" << endl;fun_static();system("pause");return 0;
}

运行结果如下:

第一次调用fun
n=10
n=11
第二次调用fun
n=10
n=11
第一次调用fun_static
n=10
n=11
第二次调用fun_static
n=11
n=12

可见,静态局部变量的效果跟全局变量有一拼,但是位于函数体内部,就极有利于程序的模块化了。

2. 全局变量

全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。

普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。

test.cpp程序代码:

int golabel1 = 2;

(1)main.cpp程序代码如下时:

#include<iostream>
using namespace std;
int golabel1 = 1;
int main()
{cout << golabel1 << endl;system("pause");return 0;
}

此时编译器报错:

错误   2   error LNK1169: 找到一个或多个多重定义的符号
错误  1   error LNK2005: "int golabel1" (?golabel1@@3HA) 已经在 test.obj 中定义 

(2)main.cpp程序代码如下时:

#include<iostream>
using namespace std;
extern int golabel1;
int main()
{cout << golabel1 << endl;system("pause");return 0;
}

此时输出结果为:

2

(3)main.cpp程序代码如下时:

#include<iostream>
using namespace std;
static int golabel1 = 1;
int main()
{cout << golabel1 << endl;system("pause");return 0;
}

此时输出结果为:

1

静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用

函数

函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:

  • 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
  • 不同的文件可以使用相同名字的静态函数,互不影响

非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明

面向对象

静态数据成员

在类内数据成员的声明前加上static关键字,该数据成员就是类内的静态数据成员。其特点如下:

  • 静态数据成员存储在全局数据区,静态数据成员在定义时分配存储空间,所以不能在类声明中定义
  • 静态数据成员是类的成员,无论定义了多少个类的对象,静态数据成员的拷贝只有一个,且对该类的所有对象可见。也就是说任一对象都可以对静态数据成员进行操作。而对于非静态数据成员,每个对象都有自己的一份拷贝。
  • 由于上面的原因,静态数据成员不属于任何对象,在没有类的实例时其作用域就可见,在没有任何对象时,就可以进行操作
  • 和普通数据成员一样,静态数据成员也遵从public, protected, private访问规则
  • 静态数据成员的初始化格式:<数据类型><类名>::<静态数据成员名>=<值>
  • 类的静态数据成员有两种访问方式:<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>

同全局变量相比,使用静态数据成员有两个优势:

  • 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性
  • 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能

静态成员函数

与静态数据成员类似,静态成员函数属于整个类,而不是某一个对象,其特性如下:

  • 静态成员函数没有this指针,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数
  • 出现在类体外的函数定义不能指定关键字static
  • 非静态成员函数可以任意地访问静态成员函数和静态数据成员

总结

static是一个很有用的关键字,使用得当可以使程序锦上添花。当然,有的公司编码规范明确规定只用于本文件的函数要全部使用static关键字声明,这是一个良好的编码风格。

无论如何,要在实际编码时注意自己的编码习惯,尽量体现出语言本身的优雅和编码者的编码素质。

C++中static关键字用法详解相关推荐

  1. C++中const关键字用法详解及实例和源码下载(一)

    最近在学习C++基础部分,看了两天书,已经看过了一遍,半知半解,回过头来重新看第二遍,深入了解一下C++的基础知识.现在读到了const关键字的用法,书上面讲解的时候并没有给出完整的实例,只是理论的讲 ...

  2. c++中static的用法详解

    C 语言的 static 关键字有三种(具体来说是两种)用途: 1. 静态局部变量:用于函数体内部修饰变量,这种变量的生存期长于该函数. 下面展示一些 内联代码片. int foo(){static ...

  3. c语言中static关键字用法详解

    概述 static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护. 但是对于c语言初学者,static由于使用灵活,并不容易掌握.本文就static在c语言中的应用进 ...

  4. python中的super用法详解_【Python】【类】super用法详解

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(sel ...

  5. java中throws用法_java中throws实例用法详解

    在程序出现异常时,会有一个抛出异常的throw出现,这里我们要跟今天所讲的throws区分开.throws的作用是声明抛出,在名称上也跟throw有所不同.下面我们就throws对策概念.语法.实例带 ...

  6. STL 中map的用法详解

    STL 中map的用法详解 Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可 ...

  7. mysql常见关键字的用法_MySQL 常用关键字用法详解

    MySQL 常用关键字用法详解 在开发工程中,操作数据库的时候经常会有不同类型的条件查询,除了使用where外,Mysql本身也提供了很多常用的关键字.本文主要介绍一些常用的关键字,像update.i ...

  8. C++中substr()函数用法详解

    C++中substr()函数用法详解 原型: string substr (size_t pos = 0, size_t len = npos) const; 返回一个新构造的string对象,其值初 ...

  9. c++中vector的用法详解

    c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...

  10. C#中NameValueCollection类用法详解

    C#中NameValueCollection类用法详解,1.NameValueCollection类集合是基于 NameObjectCollectionBase 类. 但与 NameObjectCol ...

最新文章

  1. python使用TSNE为影像组学(radiomics)数据进行降维可视化分析
  2. 圣杯布局与双飞翼布局全解
  3. JavaScript中this的五种绑定方式详解
  4. lucene索引合并与增量索引
  5. 多个线程同时运行,顺序打印问题
  6. [转].Net实现本地化简易教程
  7. 利益相关者软件工程_如何向利益相关者解释用户体验的重要性
  8. 【数据结构学习之完全从零实现所有数据结构的代码编写之二】智能指针
  9. log4j和logback的冲突导致日志输出异常
  10. androidq获取文件正式路径_android Q 新特性
  11. Deploy Office Communications Server 2007R2 Group Chat Server(一)
  12. eclipse没有Web分支Dynamic Web Project
  13. 11年写的一篇文章----智能终端安全现状及前景展望
  14. android - startActivity浅谈
  15. Mysql内连接和外连接的区别
  16. eclipse Git使用教程
  17. 日系IP的五大“坑”
  18. 沈师 PTA 数据库题目及部分解析 第十章
  19. imToken 投资 imKey 并推出通用硬件钱包方案
  20. 脉冲多普勒雷达设计附matlab代码

热门文章

  1. 循环队列的创建Java_Java版-数据结构-队列(循环队列)
  2. vue mysql交互_几种vue的数据交互形式
  3. java+log4j+是异步吗_log4j2用asyncRoot配置异步日志是如何使用disruptor
  4. 为什么 Flink 无法实时写入 MySQL?
  5. MAC环境配置SDK
  6. 字节跳动一面:如何从 100 亿 URL 中找出相同的 URL?
  7. 3d游戏计算机硬件配置方案,做三维如何配电脑?内容创作者配置推荐
  8. python选取tensor某一维_Python按维数操作多维张量,Pytorch,对,Tensor,维度
  9. zepto怎么设置宽高_【五个阿道夫】剧本杀测评 | 娱乐流量当道的时代 这个世界怎么了...
  10. mysql 创建外键语句,MySQL 创建主键,外键和复合主键的语句 | 很文博客