对于一个数据的定义,需要指定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. 原生应用native、Web应用、混合应用hybrid:3者的优缺点解析

    最近原生应用.Web应用.混合应用的名字让我们听得比较熟悉了,现在我们就通过评析各种应用的优缺点来更进一步看看这三者的区别. 一. 原生应用: 你使用过微软PowerPoint 或者 Word吧?这些 ...

  2. Node.js 参考学习地址

    前段时间研究过Node.js 自从由于笔记本硬盘崩了之后就很少在家里搞程序了,但是很想学习之,只因最近在努力学习英文.技术之外的事也需要做好,我们毕竟不是为了技术而生,技术是我们生存的一门得力技能,唯 ...

  3. 关于” fatal error C1010: unexpected end of file while looking forprecompiled header directive”问题

    其中文意思是:致命错误C1010:意想不到的文件结束而寻找预编译头文件的指令错误执行cl exe. 经过多次的查找,终于解决这问题 方法一: 在头文件中加“#include "stdafx. ...

  4. Linux内核中常见内存分配函数(三)

    ioremap void * ioremap (unsigned long offset, unsigned long size) ioremap是一种更直接的内存“分配”方式,使用时直接指定物理起始 ...

  5. OC基础5:继承

    "OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.根类即是最顶层的类,父类也可称为超类: ...

  6. SqlCommand.ExecuteScalar 方法

    本文来自:http://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.100 ...

  7. 黑马程序员 Java基础<九>---> 多线程

    ASP.Net+Android+IOS开发..Net培训.期待与您交流! 多线程 一.概述: 1.线程是什么 说到线程,我们就得先说说进程.所谓进程,就是一个正在执行(进行)中的程序,每一个进程执行都 ...

  8. jQuery.innerWidth() 函数详解

      innerWidth()函数用于设置或返回当前匹配元素的内宽度. 内宽度包括元素的内边距(padding),但不包括外边距(margin).边框(border)等部分的高度.如下图: 如果你要获取 ...

  9. z-index解决弹出层遮罩层覆盖子div不能显示输出的问题

    // 添加以下代码来进行测试: // ajax 发生错误,就会执行$('body').ajaxError(function(e, xhr, setting, text){    // e - even ...

  10. Django模板-基础知识

    上一篇中带参数的URLconf虽然可以做到传参动态显示内容,但是最终现实的内容还是硬编码到Python代码中的 def hours_ahead(request,phours): try: phours ...