对于一个数据的定义,需要指定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的更多相关文章

  1. extern、static、auto、register 定义变量的不同用法

    首先得说明什么叫“编译单元”.每个 .c 文件会被编译为一个 .o 文件,这个就是一个编译单元.最后所有的编译单元被链接起来,就是一个库或一个程序. 一个变量/函数,只要是在全局声明的,链接之后都隐含 ...

  2. 存储类型auto,static,extern,register的区别 <转>

    变量和函数的属性包括数据类型和数据的存储类别,存储类别指数据在内存中存储方式(静态和动态),包含auto,static,register,extern四种. 内存中.具体点来说内存分为三块:静态区,堆 ...

  3. 2、C语言关键字-auto register static

    文件限定符的作用: 1.auto : 局部变量,修饰的变量在栈中定义.动态内存,随着函数的结束,变量占用的内存空间也随之释放. 2.register : 寄存器变量,请求编译器将此变量存于cpu寄存器 ...

  4. C++ auto 与 register、static keyword 浅析

    [register/auto的比較分析] #include <iostream> using namespace std; int main(){ int i,sum=0; for(i=0 ...

  5. auto和register关键字

    关键字概述 很多朋友看到这儿可能会有疑问,往往其它讲C语言的书籍都是从HelloWorld,数据类型开始C语言学习的,为什么我们要从C语言的关键字开始呢?关于这点,我有两点需要说明: 本章节面向的读者 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 为openwrt编译xd-h3c

    西电老校区,openwrt上用的认证软件. 在package下新建一目录"xd-h3c",在里面新建一个Makefile,内容如下: include $(TOPDIR)/rules ...

  2. .NET委托:一个关于C#的睡前故事 【转】

    紧耦合 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺.但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒.但是彼得又不想让老板呆 ...

  3. 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.(替换原则 ...

  4. swift锁屏播放,音乐进度更新,专辑,歌手名显示

    我自己用的音乐播放器是自带的AVPlayer 导入头文件#import <MediaPlayer/MediaPlayer.h> 远程控制事件接收与处理- (void)viewWillApp ...

  5. EMCA创建em资料库时报错

    说明:监听程序配置及启动正常.实例运行正常,远程或是本地sqlplus连接实例也正常.主机名显示正常,与主机名相关三个配置文件也没问题. emca报错: [oracle@rusky-oracle11g ...

  6. 【最大流】【HDU2883】【kebab】

    题意: 有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di, 每个人要烤的肉可以分成若干份在同 ...

  7. Apache Thrift入门(安装、测试与java程序编写)

    安装Apache Thrift ubuntu linux运行: #!/bin/bash #下载 wget http://mirrors.cnnic.cn/apache/thrift/0.9.1/thr ...

  8. HTTP概念进阶

    1.什么是回调? 在Java中,就是类A调用类B中的某个方法b,然后类B又在某个时候反过来调用类A中的某个方法a,对于A来说,这个a方法便叫做回调方法 pubilc interface CallBac ...

  9. javascript 压缩空格代码演示

          压缩空格代码演示 主要是讲解 压缩一个字符串两段空格          例如:javascript函数里的空格不论是这样     var s = "Hello World     ...

  10. codevs1304 拓扑序计数

    题目描述                     Description 求一颗有根树/树形图的拓扑序个数. 输入描述                 Input Description        ...