auto, extern, register, static
对于一个数据的定义,需要指定2中属性:
存储类型和数据类型:
static int a;
auto char c;
register int d;
1 auto
2 extern
3 register
4 static
5 作用域,可见域
1 auto
1 auto自动变量必须放在函数内部。
3 register寄存器变量必须放在函数内部。
1 auto自动变量,函数调用的时候,就存在,函数结束的时候,就终止。地址都是同一地址,但是内容却反复变化。
4 static静态变量,一直存在,值没有变化,地址也没有变化。
auto用于软件工程规范,让代码清晰易懂,如果只是为了程序可以跑起来,可加可不加。
自动变量int num;等价于auto int num;
自动变量int num=10;等价于auto int num=10;
自动变量没有声明,只有定义。
int num;
int num=10;都是定义
2 extern
2 extern只有全局变量,没有局部变量。
4 static既可以放在函数外部,也可以放在函数内部,外部是静态全局变量,内部是静态局部变量。
同一个C文件,既可以访问static静态全局变量,也可以访问extern全局变量。
static静态全局变量仅仅作用于当前的C文件。
extern全局变量的定义必须放在函数外部。
需要用2个以上函数同时操作同一个变量,就必须使用全局变量。
全局变量作用域是理论上的范围,也就是程序的任何部分,无论程序有几个C文件。
作用域在任何地方,需要声明,没有合理的声明就无法使用。
特定位置,是否可见,取决于是否合理声明。
可见域,就是全局变量实际上可以引用的区域
命名规则:全局变量用大写,局部变量用小写。
创建全局变量比main函数还早。
全局变量生命期就是程序的生命期,全局变量一直占内存,而局部变量用完就扔。
需要谁都可以访问的场合就要全局变量。
全局变量可以用于函数的通信,如信用卡账户,消费,还款。
全局变量特定:生命周期很长,一直占用内存,除非程序退出;容易与局部变量重名,很容易就被屏蔽,失效。值容易被修改,例如游戏,遇到外挂一样的程序,遇到注入的黑客技术就容易被修改;全局变量可以被所有函数所共享。
使用全局变量要注意:
1名字要容易理解,尽可能不与局部变量重名。当函数内存与全局变量名相同的局部变量时,先用局部变量,没有局部变量用全局变量。
2避免占内存较大的变量使用全局变量,节约内存。
3避免全局变量被错误的修改。
4正规的软件工程,写一个函数要修改全局变量,一定要注释:为什么修改,修改的目的是什么,修改的值是多少。
extern全局变量有定义和声明的区别。
声明只是声明变量的存在,定义就是全局变量的实体。
全局变量声明:extern num;等价于extern int num;
全局变量定义:extern num=10;等价于extern int num=10;
声明可以多个,定义只有一个。
1 #define _CRT_SECURE_NO_WARNINGS
2
3 #include<stdio.h>
4 #include<stdlib.h>
5
6 int num;//声明
7 int num;//声明
8 int num = 10;//定义
9 int num = 10;//重定义,报错
10
11 main()
12 {
13
14
15 system("pause");
16 }
只有声明,不省略extern,没有定义,报错:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> extern int data;//仅仅有声明,没有定义,找不到data的实体
extern int data;
extern int data; main()
{
printf("%d\n", data); system("pause");
}
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 LNK2001 无法解析的外部符号 _date hello F:\users\denggelin\documents\visual studio 2015\Projects\hello\hello\hello.obj 1
只有声明,省略extern,没有定义,正常,系统默认初始化为0:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> int data;//仅仅有声明,没有定义,找不到data的实体
int data;
int data; main()
{
printf("%d\n", data); system("pause");
}
输出结果:
0
请按任意键继续. . .
只有声明,省略extern,没有定义,数组,系统默认初始化为0:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> int a[];
int a[];
int a[];//全部默认初始化为0 main()
{
printf("%d\n", a[]);
printf("%d\n", a[]);
printf("%d\n", a[]); system("pause");
}
输出结果:
0
0
0
请按任意键继续. . .
只有声明,省略extern,没有定义,结构体,系统默认初始化为0:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> struct info
{
int num;
char str[];
}; struct info info1;
struct info info1;
struct info info1; main()
{
printf("%d\n", info1.num);
printf("%s\n", info1.str);
printf("%d\n", info1.num);
printf("%s\n", info1.str); system("pause");
}
输出结果:
0
0
请按任意键继续. . .
extern全局变量初始化:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> #define X 6 enum info
{
A, B, C
}; int a = ;//全局变量,10是一个常量
//int b = a;//全局变量初始化不接受变量,只接受常量
int c = + ;//常量表达式也可以
int d = X;//#define常量是可以接受的
int e = sizeof(a);//sizeof是可以接受的
int f = A;//枚举常量是可以接受的 const int g = ;//不接受const,const不是真正意义上的常量,只是编译器为了保证代码不被乱修改而设定的机制
//int h = g;//C语言的const是伪常量,仅仅适用于编译器禁止修改 main()
{
system("pause");
}
3 register
1 auto自动变量必须放在函数内部。
3 register寄存器变量必须放在函数内部。
register寄存器变量在CPU,没有内存地址。
寄存器变量在CPU内部,速度快。
所以频繁使用的变量,需要放在寄存器可以提高速度。
VC会自动优化,即使没有声明寄存器变量,VC也会自动优化。
GCC就不会自动优化。
全局变量最好不要占用寄存器,占用了,会影响程序的速度。
静态变量不可以放在寄存器。
register static int num;会报错
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2159 指定了一个以上的存储类 hello F:\users\denggelin\documents\visual studio 2015\Projects\hello\hello\hello.c 17
4 static
没有static相当于乱跳槽的人,每次都要重新开始。
有static的人,等价于每次都在一个方向,要跳槽也是一个方向,就可以在一个方向达到很高的高度,每次都在积累。
1 auto局部变量,每次块语句结束,就自动回收,然后重新分配。
4 static静态局部变量,始终在内存,一旦定义初始化,即使再次执行初始化的语句,也仅仅执行一次初始化,生命周期一直占据内存,与程序共存亡。
1 auto自动变量,函数调用的时候,就存在,函数结束的时候,就终止。地址都是同一地址,但是内容却反复变化。
4 static静态变量,一直存在,值没有变化,地址也没有变化。
2 extern只有全局变量,没有局部变量。
4 static既可以放在函数外部,也可以放在函数内部,外部是静态全局变量,内部是静态局部变量。
同一个C文件,既可以访问static静态全局变量,也可以访问extern全局变量。
static静态全局变量仅仅作用于当前的C文件。
static静态局部变量,没有声明,只有定义。没有赋初值,编译器会自动赋值为0。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> main()
{
static int num; printf("%d\n", num); system("pause");
}
static静态变量,也就是循环,函数调用这些场合经常新建变量,需要静态变量。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h>
#include<windows.h> #define X 10 main()
{
for (;;)
{
static int x = ;
x++;
printf("%d\n", x);
Sleep();
} system("pause");
}
输出结果:
1
2
3
static静态全局变量,区分声明和定义。
static静态全局变量,如果没有赋值,恰好又引用,编译器会把声明当作定义,并自动赋值为0
如果有多个声明,会把最后当作定义,其他当作声明
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> static int num;
static int num;
static int num;//static静态全局变量,如果没有赋值,恰好又引用
//编译器会把声明当作定义,并自动赋值为0
//如果有多个声明,会把最后当作定义,其他当作声明 static int num = ;//定义,如果出现定义,就以定义为准 main()
{
printf("%d\n", num); system("pause");
}
输出结果:
10
请按任意键继续. . .
static静态全局变量,如果没有赋值,恰好又引用,编译器会把声明当作定义,并自动赋值为0
同理适用于数组
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> static int a[];
static int a[];
static int a[];//static静态全局变量,如果没有赋值,恰好又引用,编译器会把声明当作定义,并自动赋值为0
//同理适用于数组 main()
{
int i; for (i = ;i < ;i++)
{
printf("%d\n", a[i]);
} system("pause");
}
输出结果:
0
0
0
0
0
请按任意键继续. . .
static静态全局变量,如果没有赋值,恰好又引用,编译器会把声明当作定义,并自动赋值为0
同理适用于结构体
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> struct info
{
int num;
char name[];
}; static struct info info1;
static struct info info1;
static struct info info1; main()
{
printf("%d\n%s\n", info1.num, info1.name); system("pause");
}
输出结果:
0
请按任意键继续. . .
static静态全局变量和静态局部变量初始化:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> //static int num = a;//静态全局变量初始化不接受变量,只接受常量 main()
{
//static int num = a;//静态局部变量初始化不接受变量,只接受常量 system("pause");
}
static静态全局变量声明的作用:声明变量的存在,提升可见域。
静态局部变量,让代码的移植性更强。
把外部变量,移植到块语句内部,让代码移植性更强。
C语言默认函数可以跨文件.c调用。
static避免函数跨文件重名的问题。
static避免本个源文件的函数被外部调用。
用static说明函数:
当定义一个函数时,若在函数返回值的类型前加上说明符static,则称此函数为静态函数,又叫内部函数。
静态函数的特征是:只限于本编译单位的其他函数调用它,而不允许其他编译单位中的函数对它进行调用。
使用静态函数可以避免不同编译单位因函数同名而引起混乱。
static变量也可以作为函数参数
软件工程规范,外部函数、内部函数的声明要求:
//软件工程规范,内部函数这么声明
void msg();
void openqq(); //软件工程规范,外部函数这么声明
extern void msg();
extern void openqq();
静态局部变量
静态局部变量把重名的静态全局变量覆盖了
#include <iostream> static int a = ;//静态全局变量 void fun(); void main()
{
for (int i = ; i < a; i++)//a是静态全局变量
{
fun();
}
} void fun()
{
static int a = a;//a是静态局部变量,最初赋值为0
std::cout << (a += ) << std::endl;
}
输出结果:
2
4
请按任意键继续. . .
静态全局变量
#include <iostream> static int a = ;//静态全局变量 void fun(); void main()
{
for (int i = ; i < a; i++)//a是静态全局变量
{
fun();
}
} void fun()
{
static int a = ::a;//左边a是静态局部变量,右边::a是静态全局变量
std::cout << (a += ) << std::endl;
}
输出结果:
5
7
请按任意键继续. . .
5 作用域,可见域
作用域就是理论上函数可以调用的地方,可见域就是实际上可以调用的地方。
结构体变量的作用域与可见域
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> struct info//结构体类型定义在外部,就是从定义开始到当前源文件结束的范围
{
int num;
char name[];
}; struct info info1; main()
{
struct data//结构体类型定义在内部,就是从定义开始到当前块语句结束的范围
{
int num;
char name[];
}; system("pause");
}
结构体变量作为全局变量与局部变量:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
#include<stdlib.h> struct info//结构体类型定义在外部,就是从定义开始到当前源文件结束的范围
{
int num;
char name[];
}; //结构体变量作为全部变量,有声明与定义的差别。不赋值初始化就是声明,初始化就是定义。
struct info info1;
struct info info1;
struct info info1;//都是声明,声明只是说明存在,可以有多个 main()
{
//struct info info1;//结构体变量作为局部变量,没有声明与定义的区别,有没有初始化,都是定义 struct info info1; //info1作为一个结构体变量,从当前定义开始,到当前的块语句结束,就是结构体变量的作用域 info1.num = ; system("pause");
}
不同的源文件引用外部结构体变量,不仅需要外部声明,还需要结构体定义
结构体类型最多适用于1个c文件,不同的c文件快于包含同名同类型的结构体类型,也可以包含同名不同类型的结构体类型
同一源文件中,函数外部,结构体类型定义最多只能有1个
同一源文件中,同一个块语句中,结构体类型定义最多只能有1个,如果不同块语句,同名可以有多个
栈区、堆区都是动态存储区,栈区调用的时候分配,用完的时候回收再次分配。
堆区,自己自由分配,自己决定何时分配,何时回收。
代码区、静态区,就一直存在,与程序共存亡。
auto, extern, register, static的更多相关文章
- extern、static、auto、register 定义变量的不同用法
首先得说明什么叫“编译单元”.每个 .c 文件会被编译为一个 .o 文件,这个就是一个编译单元.最后所有的编译单元被链接起来,就是一个库或一个程序. 一个变量/函数,只要是在全局声明的,链接之后都隐含 ...
- 存储类型auto,static,extern,register的区别 <转>
变量和函数的属性包括数据类型和数据的存储类别,存储类别指数据在内存中存储方式(静态和动态),包含auto,static,register,extern四种. 内存中.具体点来说内存分为三块:静态区,堆 ...
- 2、C语言关键字-auto register static
文件限定符的作用: 1.auto : 局部变量,修饰的变量在栈中定义.动态内存,随着函数的结束,变量占用的内存空间也随之释放. 2.register : 寄存器变量,请求编译器将此变量存于cpu寄存器 ...
- C++ auto 与 register、static keyword 浅析
[register/auto的比較分析] #include <iostream> using namespace std; int main(){ int i,sum=0; for(i=0 ...
- auto和register关键字
关键字概述 很多朋友看到这儿可能会有疑问,往往其它讲C语言的书籍都是从HelloWorld,数据类型开始C语言学习的,为什么我们要从C语言的关键字开始呢?关于这点,我有两点需要说明: 本章节面向的读者 ...
- [C]控制外部变量访问权限的extern和static关键字
一.extern 概述 编译器是由上至下编译源文件的,当遇到一些函数引用外部全局变量,而这个变量被定义在该函数声明主体的下方,又或者引用自其它的编译单元,这个情况就需要extern来向编译器表明此变量 ...
- 链接(extern、static关键词\头文件\静态库\共享库)
原文链接:http://www.orlion.ga/781/ 一. 多目标文件的链接 假设有两个文件:stack.c: /* stack.c */ char stack[512]; int top = ...
- IOS的变量前加extern和static字段
IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...
- 全局变量,extern和static以及命名空间的区别
全局变量,extern和static以及命名空间的区别 全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...
随机推荐
- 代码管理git总结
1. http://blog.csdn.net/teresa502/article/details/7388834 pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 ...
- iOS伪实现打地鼠游戏
打地鼠是一款可以用iOS知识来实现的一种游戏.其核心技术就是通过imageView来播放动画,点击button时来停止当前播放的动画开始击打地鼠的动画.话不多说直接上代码. 这是添加当前的背景图片,然 ...
- Android SDK目录结构和工具介绍
Android SDK目录结构和工具介绍是本文要介绍的内容,主要是来了解并学习Android SDK的内容,具体关于Android SDK内容的详解来看本文. AD: Android SDK目录结构和 ...
- poj 2393 Yogurt factory(dp+贪心)
奶牛们建了一家酸奶厂,在N周内每周需要出货Y_i单位酸奶,第i周成本为C_i,储存费为每周S.求总体最低成本. 贪心策略是维持每周的最低单位成本,每周可能用上周剩下的,也可能生产新的.于是该周单位成本 ...
- C语言---整型字符串转换
C语言提供了几个标准库函数,能够将随意类型(整型.长整型.浮点型等)的数字转换为字符串.下面是用itoa()函数将整数转 换为字符串的一个样例: # include <stdio.h> ...
- 每日一小练——Eratosthenes 筛选法
上得厅堂.下得厨房,写得代码.翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:Eratosthenes筛选法 内容: 求质数是一个非常普遍的问题,通常不外乎用数去除.除到不尽时,给定的数就是质数.可是 ...
- 傅老师课堂:Java高级应用之Struts2+Spring2+Hibernate3大集成
开篇一笑:一对情侣,非常恩爱,但男友喜欢说脏话,一天女友提出要带男友回家吃个饭,见见家长,千叮万嘱让男友别说脏话,男友在家憋了一晚上没说一句脏话,天气寒冷,到走的时候女友家长要出来送他们,男友客气的说 ...
- .net 链接ORACLE的安装包
odp.net.ma
- sql必知必会(第四版) 学习笔记一
温习一遍简单的sql语法,把自己掌握还不够的地方,做了些笔记.... 1 去重复关键词,distinct select distinct sname from student; 2 限制结果top的用 ...
- Js闭包的用途
本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...