变量和函数的属性包括数据类型和数据的存储类别,存储类别指数据在内存中存储方式(静态和动态),包含auto,static,register,extern四种。

内存中。具体点来说内存分为三块:静态区,堆区,栈区。外部变量和全局变量存放在静态区,局部变量存放在栈区,动态开辟的内存存在堆区。 

一、简要性比较

extern   外部变量声明,是指这是一个已在别的地方定义过的对象,这里只是对变量的一次重复引用,不会产生新的变量。 
static   静态数据,数据存放在全局数据区,但作用域只是本 文件/函数 中,所以你可以在两个不同的文件/函数内部申明同名的static变量,但是           它们是两个不同的全局变量。 如果是定义在函数内,那么该对象具有无链接,函数外不能对其访问。如果是定义在函数外,那么该对象具          有内部链接,其它程序文件不能对其访问
auto     普通局部栈变量,是自动存储,这种对象会自动创建和销毁 ,建议这个变量要放在堆栈上面,调用函数时分配内存,函数结束时释放内            存。一般隐藏auto默认为自动存储类别。我们程序都变量大多是自动变量。
register 寄存器变量,请求编译器将这个变量保存在CPU的寄存器中,从而加快程序的运行.

系统的寄存器是有限制的,声明变量时如:register int i.这种存储类型可以用于频繁使用的变量。

二、补充注意点

1、auto存储类型的变量只能在某个程序范围内使用,他采用堆栈的方式分配空间。

在定义变量时,auto是可以省略的,如:auto   int   i;等效于int   i.

2、全局变量不允许声明为auto变量,register不适用于全局变量。

3、register是不能取址的。比如 int i;(自动为auto)int *p=&i;是对的, 但register int j; int *p = &j;是错的,因为无法对寄存器的定址。

4.声明变量为register,编译器并不一定会将它处理为寄存器变量,毕竟,资源是有限的。

5、实际上现在一般的编译器都忽略auto和register申明,现在的编译器自己能够区分最好将那些变量放置在寄存器中,那些放置在堆栈中;甚至于将一些变量有时存放在堆栈,有时存放在寄存器中。

6.auto register 是用来修饰变量的,static extern 变量函数都可以

三、详细说明

从变量值存在时间(生存期)角度分:静态存储方式和动态存储方式。

从变量的作用域(空间)角度分:全局变量和局部变量。

在用户区的存储空间:

|程序区    |

|静态存储区|

|动态存储器|

静态存储方式程序运行期间系统分配固定存储空间,动态存储方式根据需求动态分配存储空间。全局变量都存放于静态存储区,动态存储区主要包括:函数的形参,在函数调用时分配存储空间;自动变量(未加static声明的局部变量);函数调用时的现场保护和返回地址等。

Auto自动变量:一般隐藏auto默认为自动存储类别。我们程序都变量大多是自动变量。

Static变量::static声明的局部变量在函数调用结束后不释放存储空间,再次调用函数时该变量已经有值。其他函数时不能引用它的。Static局部变量时在编译赋初值,自动变量的初值是函数调用时赋的。所以局部变量不赋初始值的话static变量自动赋值0或在空字符。而自动变量的初值则是不确定的。最好不要直接使用。函数中需要保留上次调用时的值或者初始化之后变量只被引用而不改变的可以考虑用static局部变量,这样比较耗内存。

Register变量:动态和静态变量都是存放在内存中,程序中遇到该值时用控制器发指令将变量的值送到运算器中,需要存数再保存到内存中。如果频繁使用一个变量,比如一个函数体内的多次循环每次都引用该局部变量,我们则可以把局部变量的值放到CPU的寄存器中,叫寄存器变量。不需要多次到内存中存取提高效率。但是只能局部自动变量和形参可以做寄存器变量。在函数调用时占用一些寄存器,函数结束时释放。不同系统对register要求也不一样,比如对定义register变量个数,数据类型等限制,有的默认为自动变量处理。所以在程序一般也不用。

Extern外部变量:如果我们希望该外部变量只能在本文件内使用,而不能被其他文件引用可以在外部变量定义时加static声明。防止别人写的模块误用。在函数外部定义的全局变量,作用域开始于变量定义,结束于程序文件的结束。我们可以extern来声明外部变量来扩展它的作用域。同一个文件内,extern声明之后就可以作用域扩大到声明处到文件结束。比如在一个函数之后定义外部变量a,之后的函数可以使用该变量,但是之前的函数不能使用,加extern可以解决。多个文件时,可以在未定义该外部变量的文件内做extern声明即可以使用。但是需要注意可能执行一个文件时改变了该全局变量的值,影响其他文件的调用。编译时遇到extern,会先在文件内找是否定义了该外部变量。如果未找到则在链接时在其他文件中找。

四、示例

1、extern:

extern的对象都具有静态生命周期。使用extern时,注意不能重复定义,否则编译报错,如:
程序文件一:
extern int a = 10; //编译警告,extern的变量最好不要初始化
程序文件二:
extern int a = 20; //重复定义,应改为extern int a;
一般最好这样,如果需要初始化,可把extern修饰符去掉(但也不要重复定义),另外如果其它程序文件也需要用到该变量,可用extern来声明该变量。

2.

1. 局部变量: 也叫自动变量, 它声明在函数开始, 生存于栈, 它的生命随着函数返回而结束.

#include <stdio.h>int main(void)
{auto int i = 9; /* 声明局部变量的关键字是 auto; 因可以省略, 几乎没人使用 */   printf("%d\n", i);  getchar();return 0;
}

2. 全局变量:  声明在函数体外 , 一般应在函数前; 每个函数都可以使用它, 不过全局变量应尽量少用.

#include <stdio.h>void add(void);
void mul(void);
int gi = 3; /* 全局变量 */
int main(void)
{    printf("%d\n", gi);  /* 3  */add();printf("%d\n", gi);  /* 5  */mul();printf("%d\n", gi);  /* 10 */getchar();return 0;
}
void add(void) {gi += 2;
}
void mul(void) {gi *= 2;
}

全局变量会被初始化为空, 而局部变量在没有赋值前是一个垃圾值:

#include <stdio.h>int gi; /* 全局变量 */
int main(void)
{int i; /* 句柄变量 */printf("%d, %d\n", gi, i);getchar();return 0;
}

当全局变量与局部变量重名时, 使用的是局部变量:

#include <stdio.h>int a = 111, b = 222;
int main(void)
{int a = 123;printf("%d,%d\n", a, b); /* 123,222*/getchar();    return 0;
}

3. static 关键字: 修饰的局部变量是静态局部变量; 静态局部变量存值如同全局变量 , 区别在于它只属于拥有它的函数; 它也会被初始化为空.

#include <stdio.h>void fun1(void);
void fun2(void);
int main(void)
{    int i;for (i = 0; i < 10; i++) fun1();printf("---\n");for (i = 0; i < 10; i++) fun2();getchar();return 0;
}
void fun1(void) {int n = 0;        /* 一般的局部变量 */printf("%d\n", n++);
}
void fun2(void) {static int n;     /* 静态局部变量; 会被初始化为空 */printf("%d\n", n++);
}

用 static 关键字修饰的全局变量是静态全局变量; 静态全局变量只能用于定义它的单元.

//譬如在 File1.c 里面定义了:
static int num = 99;  /* 去掉前面的 static 其他单元才可以使用 */
//在 File2.c 里使用:
#include <stdio.h>extern int num;
int main(void)
{    printf("%d\n", num);getchar();return 0;
}
#include <stdio.h>
int fun(void);int main(void){ int i; for (i = 0; i < 10; i++) { printf("函数被调用了 %2d 次;\n", fun()); } getchar(); return 0;}int fun(void) { static int n; return ++n;}4. 寄存器变量(register):寄存器变量会尽量把变量放到寄存器(而不是栈或堆), 从而加快存取速度
#include <stdio.h>
#include <time.h>#define TIME 1000000000int m, n = TIME; /* 全局变量 */
int main(void)
{   time_t start, stop;register int a, b = TIME; /* 寄存器变量 */int x, y = TIME;          /* 一般变量   */time(&start);for (a = 0; a < b; a++);time(&stop);printf("寄存器变量用时: %d 秒\n", stop - start);time(&start);for (x = 0; x < y; x++);time(&stop);printf("一般变量用时: %d 秒\n", stop - start);time(&start);for (m = 0; m < n; m++);time(&stop);printf("全局变量用时: %d 秒\n", stop - start);getchar();return 0;
}

4. extern 关键字:
使用外部全局变量应该用 extern 重新声明一下;
如果不使用 extern, 将是重新定义;
在链接阶段, 同一程序中不同单元的全局变量是共用的所以不能重新定义;
本例为了省事并没有涉及另一个文件, 只是把变量放在文件尾模拟了一下.

另外, extern 主要还是用于函数.

#include <stdio.h>extern int g1;
int main(void)
{    extern int g2;printf("%d,%d\n", g1,g2);  getchar();return 0;
}
int g1 = 77;
int g2 = 88;

5. volatile 关键字:

程序在使用变量时, 特别是连续多次使用变量时, 一般是载入寄存器, 直接从寄存器存取, 之后再还回内存;
但如果此变量在返回内存时, 假如内存中的值已经改变了(从外部修改了)怎么办?
为了避免这种情况的发生, 可以用 volatile 说明此变量, 以保证变量的每次使用都是直接从内存存取.
但这样肯定会影响效率, 幸好它并不常用.

另外: 如果 const volatile 同时使用, 这表示此变量只接受外部的修改.

#include <stdio.h>volatile int num = 123;
int main(void)
{    printf("%d\n", num);getchar();return 0;
}

6. restrict 关键字:

restrict 有点和 volatile 相反; 不过 restrict 只是对指针.
好像 C++Builder 2009 并不支持它, 暂时无法测试. 

原文地址: http://blog.csdn.net/firefly_2002/article/details/7940802


存储类型auto,static,extern,register的区别 转相关推荐

  1. 存储类型auto,static,extern,register的区别

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

  2. 【 C 】作用域、链接属性、存储类型、static 关键字简介及总结

    目录 作用域 代码块作用域 文件作用域 原型作用域 函数作用域 链接属性 存储类型 总结 作用域 当变量在程序中的某个部分被声明时,它只有在程序的一定区域才能被访问.这个区域由标识符的作用域(scop ...

  3. C语言——变量篇(一)变量关键字static、auto、extern、register

    前言:笔者最近在看C语言时候遇到了一堆关键字,auto,static,extern,register等等.看上去头皮发麻,在这里整理一下,便于自己理解. 全局变量和局部变量 关于全局变量和局部变量,笔 ...

  4. C语言中【变量】的存储类型共有4种类型

    在C语言中,对变量的存储类型说明有以下四种:   auto          自动变量 (动态存储) register     寄存器变量(动态存储) extern       外部变量(静态存储) ...

  5. C/C++中存储类型

    c语言中的存储类型有auto, extern, register, static 这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有 数据区.bbs区.栈区. ...

  6. C语言:存储类型,内存管理

    一.存储类型 在定义一个数据(变量/数组)的时候,除了需要定义数据类型外,还需要定义存储类型.数据类型用于说明变量的长度和存储方式,而存储类型用于说明变量的使用规则 1.存储类型的分类 <1&g ...

  7. C/C++ 存储类型 作用域 连接类型

    1)存储类型:   标准C语言为变量,常量和函数定义了4种存储类型:extern,auto,static,register. 这4种存储类型可分为两种生存期限:永久的(在整个程序执行期都存在)和临时的 ...

  8. C/C++中涉及存储方式的关键字:auto,static,register,extern2009-01-22 11:23auto关键字:

    C/C++中涉及存储方式的关键字:auto,static,register,extern 2009-01-22 11:23 auto关键字: auto对象和变量被存储在栈中,它的生命周期仅存在于它的声 ...

  9. 关键字:auto、static、register、const、volatile 、extern 总结

    auto 这个这个关键字用于声明变量的生存期为自动,即将不在任何类.结构.枚举.联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量.这个关键字不怎么多写,因为所有的变量默认就是aut ...

最新文章

  1. underscorejs之 _.indexBy(list, iteratee, [context])
  2. 如何快速将下载好的大量源代码文件加入到VS项目中
  3. linux 基准测试_如何对Linux系统进行基准测试:3个开源基准测试工具
  4. linux操作系统分析 课程,《Linux操作系统》课程的现状与分析
  5. github private链接访问_将github配置为图床+PicGo配置
  6. python实验八分支语句_python语句(分支,循环)
  7. Logistic Regression逻辑回归的简单解释
  8. 3D游戏建模就是那么简单
  9. 新版Windows Live SkyDrive Beta发布
  10. 3.MongoDB uri中包含特殊字符与读策略配置
  11. OUTLOOK新邮件到达提醒设置以及outlook最小化到托盘设置
  12. searchBar没有光标解决方法
  13. 华三交换机链路聚合的几点思考
  14. c语言要计算20,用C语言计算1~20的阶乘之和
  15. 【Proteus仿真】NE555延时电路
  16. 阿里云银行卡验证四要素
  17. 电商(一) 创建订单业务流程
  18. 三原色图(最小生成树 kruskal)
  19. 你不曾了解的CVTE的某个部门
  20. win7安全模式如何打开计算机管理,Win7安全模式怎么进?Win7进入安全模式方法

热门文章

  1. 用汇编写系统服务程序
  2. 手把手教你使用Python生成图灵智能小伙伴
  3. 为什么程序员的社会地位不高?
  4. 关于mysql的项目_项目中常用的MySQL 优化
  5. 项目下创建文件_Linux 下创建和使用交换文件
  6. python批量将pdf转成word_如何用Python把pdf转换成word
  7. STM32----ADC多通道采集
  8. Nature Reviews Cancer综述:长非编码RNA在肿瘤转移中的作用
  9. 机器学习 - 随机森林手动10 折交叉验证
  10. 复现nature communication PCA原图|代码分析(一)