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

标识符:标识符不仅仅代表着变量的名字,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. Studio for WPF:使用 C1TileView 创建图片库

    C1TileView 提供了数据交互浏览的功能.允许我们设置最大化和最小化浏览模板,我们可以通过最小化模板快速定位详细浏览选项. 下面我们分步分享实现方法: 1.添加 C1TileView 到窗体,并 ...

  2. LeetCode132:Palindrome Partitioning II

    题目: Given a string s, partition s such that every substring of the partition is a palindrome. Return ...

  3. JAVA多用户商城系统源码

    最近公司要搞商城,让我多方咨询,最后看了很多,要不就是代码注释不全,要不就是bug多,要么就是文档缺少,最后决定自己开发一套商城. 下面是开发的一些心得体会,权且记录下来,给自己做个记录把.   网址 ...

  4. CentOS7.2设置zabbix

    准备工作 1.lnmp或lamp环境,本机环境:CentOS 7.2 64位,nginx1.10.2 php5.6.26 mysql5.7.15 2.软件Zabbix wget http://nchc ...

  5. PHP学习笔记:MySQL数据库的操纵

    Update语句 Update 表名 set 字段1=值1, 字段2=值2  where  条件 练习: 把用户名带  ‘小’的人的密码设置为123456@ 语句:UPDATE crm_user SE ...

  6. Android 手机卫士14--Widget窗口小部件AppWidgetProvider

    1.AndroidManifest.xml根据窗体小部件广播接受者关键字android.appwidget.action.APPWIDGET_UPDATE 搜索android:resource=&qu ...

  7. 给我一个及时的问候——XMPP

    XMPP总的来说就是:基于XML数据结构,点对点的,及时通讯协议 是 Linux操作系统+Apache软件+mySql数据库 + php 编程语言 组成   开始时要导入 XMPPFrameWork框 ...

  8. iOS开发之网络编程--使用NSURLConnection实现文件上传

    前言:使用NSURLConnection实现文件上传有点繁琐.    本文并没有介绍使用第三方框架上传文件. 正文: 这里先提供用于编码测试的接口:http://120.25.226.186:3281 ...

  9. Objective-C之@class的使用

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  10. Linux的文件权限

    1 文件权限的表示 (1)字母表示法 Linux中所有文件(普通文件.目录文件.字符特殊文件.块特殊文件.管道或FIFO.符号链接.套接字)都有9个权限,如下图所示: -rw-rw-r--就是文件a的 ...