在进入正题前我们必须了解一些概念:

标识符:标识符不仅仅代表着变量的名字,main()函数的main也是一个标识符,这点很重要。

存储类型:即变量的存储位置及其生存周期:
静态区:分为两块
.date 已显式初始化的全局变量了静态变量
.bss 存放未初始化的全局或者静态变量

注意:
静态变量的初值是在编译时就进行初始化了;
意思就是用static修饰的变量赋过数值的话就保存为他的初值,如果没有初始化的话就赋值为零,且整个程序只初始化一次;
即不管static int i = 1;或者这 static int a 在程序中的什么位置;分别由编译器初值装入1和0保存在静态区
注意初始化只执行一次;看如下例子:
#include <stdio.h>

void add()
{
  static a;
  static b = 1;
  printf("%d\t",a++);
  printf("%d\n",b++);
}

int main()
{
  int i = 0;
  for(;i<5 ;i++)
  {
    add();
  }
return 0;
}
的结果为:
0 1
1 2
2 3
3 4
4 5

堆栈区:

栈:系统自动分配和释放:例如局部变量函数或者代码块结束时释放因为就是局部变量存储在栈区。
堆:开发者自己生申请和释放(例如调用void *malloc())。它的生存周期是开发者决定的。
当你使用malloc的是后被造出来,free后被销毁。

常量区:存储常量数据;编译完成后到程序结束都存在,可以访问但是不能被修改。

链接属性:
假设我们有很多.c文件一起生成一个可执行文件例如:
test0.c   test1.c    test2.c
|       |        |
|       |               |
|         |               |
test0.o     test1.o          test2.o
|        |       |
——————————————链接
                    |
                   test

链接的作用就是将各个二进制代码文件链接生成一个可执行文件所以不管是我们写了多少个c文件最后都是要被合成一个的,
这个时候我们就该考虑一个问题各个文件的标识符是否公用,因此便引出了链接属性。

c规定链接属性分为三种:
external(全局的):各个文件访问的是同一个标识符。
internal(局部的):标识符只被该文件中定义后的地方能访问。
none(无链接属性):没有链接属性。

作用域:即标识符能被访问的代码区域大小。
代码块作用域:在代码块中定义的标识符只在定义的开始和代码块的时候能被访问,即使是被声明为静态不能使作用域扩大,这个下面会提到。
文件作用域:一般指全局变量和函数,即在整个文件中从定义的起始的位置后都能被访问。
原型作用域:即形参的作用域,一般就是在整个函数代码块中有效,它的存在是防止我们多次在函数内定义一个和形参标识符的名字冲突的标识符
因为这样我们会失去形参的值。
函数作用域:这个是用来说代码标号的作用区域的,所以他和goto有关,呵呵,我看了一眼就忘了。

下面来看几个关键字()

auto:进入程序时在栈创建,程序结束自动释放。一般局部变量自带auto属性。所以用的很少。

static:
1:用于修饰局部变量时修改的是其存储类型,使其成为静态存储。至于局部变量静态存储后的变量有什么改变参照上文的解释和例子。但是作用域不改变。
2:修饰全局标识符时,意思是将全局变量的external属性修改为internal。但是作用域不改变。
3:修饰函数时是修改它的链接属性external属性修改为internal。但是作用域不改变;

extern:
1.修饰变量时声明这个变量定义在别的文件中或者本文件其他位置的external属性的变量,一般用来修饰全局标识符(变量函数);
注意:
如果我们在标识符声明时,一旦是在函数块外部声明,那么编译器默认加多上一个external属性,而不是extern修饰符。这很重要容易混淆。
而在代码块中声明的局部变量则会被带上一个intenral的链接属性。但这不代表他只能在代码块的属性是intenral的链接属性赋予的。
真正的原因是因为局部变量被看作一个auto类型的变量。

register:即存储在寄存器中的变量,寄存器有什么特点大家都知道寄存器的取数效率很高常用于重复的变量运算。注意
不能用全局变量去申请,一般默认为auto,这和全局变量的生命周期有关。

总结:千万不能把extern和external与static与internal混淆。他们的具体解释看上文。
狗日的公司笔试其和考试题经常拿这个来考人。就像下面这个:
#include "stdio.h"
int a=1;

int f(int c)
{
  static int a=2;
  c=c+1;
return (a++)+c;
}
main()
{
  int i,k=0;
  for(i=0;i<2;i++)
  {
    int a=3;
    k+=f(a);
  }
  k+=a;
  printf("%d\n",k);
}
我们只要根据上文提到的知识:把变量表示符一换,就可以了:
#include "stdio.h"
int a=1;

int f(int c)
{
  static int b=2;
  c=c+1;
return (b++)+c;
}
main()
{
  int i,k=0;
  for(i=0;i<2;i++)
  {
    int d=3;
    k+=f(d);
   }
  k+=a;
  printf("%d\n",k);
}

问题及解决,妈妈再也不用担心我的学习。

关于extern和static关键字引出的一些关于作用域和链接属性和存储类型的问题的更多相关文章

  1. C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static

    1.变量的声明 声明变量的基本形式: 说明符号(一个或者多个) 声明表达式列表 说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作 ...

  2. C++中extern “C”含义及extern、static关键字浅析

    https://blog.csdn.net/bzhxuexi/article/details/31782445 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C ...

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

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

  4. C语言的存储类型和关键字extern、static

    1.C语言中每个变量都有3个性质:存储期限.作用域.链接 1)存储期限:变量的存储期限决定了为变量预留的内存被释放的时间.共2种,自动存储期限(auto),静态存储期限(static),自动存储(au ...

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

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

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

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

  7. C语言中的static关键字

    C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错.伴随着不同源文件变量和函数之间的相互 ...

  8. static关键字 详解

    原文地址:http://blog.csdn.net/keyeagle/article/details/6708077 google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇 ...

  9. C/C++ static 关键字

    在 C/C++ 中,static 关键字使用恰当能够大大提高程序的模块化特性. static 在 C++ 类之中和在类之外的作用不一样,在C语言中的作用和在 C++ 类之外的作用相同,下面一一说明: ...

随机推荐

  1. c#重点[数据类型,构造方法,变量,变量,运算符,装箱,拆箱]

    1.命名规范    类  :名词 每个单词的首字母大写 Dog Student  PersonClass 字段:首个字母小写,如果有多个单词,后面的单词首字母大写 string name=" ...

  2. C#中弹出文件选择窗体和判断是否下载提示窗体的源码

    1.创建一个window窗体

  3. eclipse中的web项目路径和发布好的项目路径

    现在企业开发中,我们都会创建一个javaWeb工程,在eclipse中指的是新建一个dynamic web project,创建完工程之后,我们在IDE中大体看到如下的工程目录: 我们主要关心的文件夹 ...

  4. ahjesus配置vsftpd和xinetd

    vsftpd的简单配置参考此教程 传送门 教程内xinetd的配置失效, 用xinetd方式启动ftp方式如下 1.在/etc/xinetd.d/目录中创建一个文件vsftpd 内容如下: servi ...

  5. Android 手机卫士13--进程设置

    1.显示隐藏系统进程 修改ProcessManagerActivity的Adapter ..... @Override public int getCount() { if(SpUtil.getBoo ...

  6. 为什么不推崇复杂的ORM

    上一篇文章写完,回复的人很多,有的说的很中肯,有的貌似只是看到文章的标题就进来写评论的!还有人问为什么我要屏蔽掉[反对]按钮,因为谁写文章都是为了分享,都在说出自己的心得体会.不过由于大家遇到的项目, ...

  7. SAP内存/ABAP内存/共享内存区别

    (1).读取和使用方法不同SAP内存使用SET/GET parameters方法:SET PARAMETER ID 'MAT' field p_matnr.GET PARAMETER ID 'MAT' ...

  8. Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结

    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word  excel pdf 的web预览要求 ...

  9. “Stamping” PDF Files Downloaded from SharePoint 2010

    http://blog.falchionconsulting.com/index.php/2012/03/stamping-pdf-files-downloaded-from-sharepoint-2 ...

  10. 据说是百度ios面试题

    百度面试题:   一面:知识点 Objective C runtime library: Objective C的对象模型,Block的底层实现结构,消息发送,消息转发,内存管理 CoreData : ...