对于一个数据的定义,需要指定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. 代码管理git总结

    1. http://blog.csdn.net/teresa502/article/details/7388834 pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 ...

  2. iOS伪实现打地鼠游戏

    打地鼠是一款可以用iOS知识来实现的一种游戏.其核心技术就是通过imageView来播放动画,点击button时来停止当前播放的动画开始击打地鼠的动画.话不多说直接上代码. 这是添加当前的背景图片,然 ...

  3. Android SDK目录结构和工具介绍

    Android SDK目录结构和工具介绍是本文要介绍的内容,主要是来了解并学习Android SDK的内容,具体关于Android SDK内容的详解来看本文. AD: Android SDK目录结构和 ...

  4. poj 2393 Yogurt factory(dp+贪心)

    奶牛们建了一家酸奶厂,在N周内每周需要出货Y_i单位酸奶,第i周成本为C_i,储存费为每周S.求总体最低成本. 贪心策略是维持每周的最低单位成本,每周可能用上周剩下的,也可能生产新的.于是该周单位成本 ...

  5. C语言---整型字符串转换

    C语言提供了几个标准库函数,能够将随意类型(整型.长整型.浮点型等)的数字转换为字符串.下面是用itoa()函数将整数转 换为字符串的一个样例: # include <stdio.h>   ...

  6. 每日一小练——Eratosthenes 筛选法

    上得厅堂.下得厨房,写得代码.翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:Eratosthenes筛选法 内容: 求质数是一个非常普遍的问题,通常不外乎用数去除.除到不尽时,给定的数就是质数.可是 ...

  7. 傅老师课堂:Java高级应用之Struts2+Spring2+Hibernate3大集成

    开篇一笑:一对情侣,非常恩爱,但男友喜欢说脏话,一天女友提出要带男友回家吃个饭,见见家长,千叮万嘱让男友别说脏话,男友在家憋了一晚上没说一句脏话,天气寒冷,到走的时候女友家长要出来送他们,男友客气的说 ...

  8. .net 链接ORACLE的安装包

    odp.net.ma

  9. sql必知必会(第四版) 学习笔记一

    温习一遍简单的sql语法,把自己掌握还不够的地方,做了些笔记.... 1 去重复关键词,distinct select distinct sname from student; 2 限制结果top的用 ...

  10. Js闭包的用途

    本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...