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以及命名空间的区别 全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...
随机推荐
- 为openwrt编译xd-h3c
西电老校区,openwrt上用的认证软件. 在package下新建一目录"xd-h3c",在里面新建一个Makefile,内容如下: include $(TOPDIR)/rules ...
- .NET委托:一个关于C#的睡前故事 【转】
紧耦合 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺.但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒.但是彼得又不想让老板呆 ...
- edit distance leetcode
这样的字符转换的dp挺经典的, 若word1[i+1]==word2[j+1] dp[i+1][j+1] = dp[i][j]:否则,dp[i+1][j+1] = dp[i][j] + 1.(替换原则 ...
- swift锁屏播放,音乐进度更新,专辑,歌手名显示
我自己用的音乐播放器是自带的AVPlayer 导入头文件#import <MediaPlayer/MediaPlayer.h> 远程控制事件接收与处理- (void)viewWillApp ...
- EMCA创建em资料库时报错
说明:监听程序配置及启动正常.实例运行正常,远程或是本地sqlplus连接实例也正常.主机名显示正常,与主机名相关三个配置文件也没问题. emca报错: [oracle@rusky-oracle11g ...
- 【最大流】【HDU2883】【kebab】
题意: 有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di, 每个人要烤的肉可以分成若干份在同 ...
- Apache Thrift入门(安装、测试与java程序编写)
安装Apache Thrift ubuntu linux运行: #!/bin/bash #下载 wget http://mirrors.cnnic.cn/apache/thrift/0.9.1/thr ...
- HTTP概念进阶
1.什么是回调? 在Java中,就是类A调用类B中的某个方法b,然后类B又在某个时候反过来调用类A中的某个方法a,对于A来说,这个a方法便叫做回调方法 pubilc interface CallBac ...
- javascript 压缩空格代码演示
压缩空格代码演示 主要是讲解 压缩一个字符串两段空格 例如:javascript函数里的空格不论是这样 var s = "Hello World ...
- codevs1304 拓扑序计数
题目描述 Description 求一颗有根树/树形图的拓扑序个数. 输入描述 Input Description ...