static关键字有两类使用:函数外使用和和函数内使用,其中函数外使用主要用来限制被修饰的函数或变量作用域为本文件,没什么可多说的,下面重点说一下static关键字在函数体内的用法.

如下面的代码:

#include<stdio.h>
void test(){static int a=1;printf("%d",a++);
}
void main(){int i;for (i=0;i<5;i++)test();
}

输出为12345,如果去掉static关键字,输出将是11111.
我们来看一下使用了static关键字后的汇编代码(只保留了关键部分):

.LC0:.string "%d"test:
.LFB0:pushl   %ebpmovl    %esp, %ebpsubl    $8, %espmovl    a.1933, %eaxleal    1(%eax), %edxmovl    %edx, a.1933subl    $8, %esppushl   %eaxpushl   $.LC0call    printfaddl    $16, %espnopleavereta.1933:.long   1

可以看到下面三行汇编代码实际完成的是a++操作,如果有不理解第二条指令的可以参考我的上一篇博客.

        movl    a.1933, %eaxleal    1(%eax), %edxmovl    %edx, a.1933

等等,我的变量名不是a吗?a.1933是什么玩意儿?其实这个a.1933像极了一个全局变量.不信看下面的代码:

#include<stdio.h>
int a=1;
void test(){printf("%d",a++);
}
void main(){int i;for (i=0;i<5;i++)test();
}

其关键的汇编代码为:

a:.long   1
.LC0:.string "%d"
test:
.LFB0:pushl   %ebpmovl    %esp, %ebpsubl    $8, %espmovl    a, %eaxleal    1(%eax), %edxmovl    %edx, asubl    $8, %esppushl   %eaxpushl   $.LC0call    printfaddl    $16, %espnopleaveret

看看,何止像,从汇编的角度来看,这里的a和上面的a.1933根本就是一回事嘛.所以函数内的static变量和全局变量从汇编的角度看本质上是一样的.这也就解释了为什么test()退出后static修饰的a还存在的问题,因为人家跟全局变量的地位一样嘛.那如何解释1933这个后缀呢?其实这个是C编译器的限制,也就是说你只有在汇编后才知道函数内static修饰的变量真正叫什么名字,而这个名字只在该函数体内才知道,外部函数是不知道这个真名的.换句话说,C编译器就是靠这个别名的办法限制了外部函数对其的访问.
但是由于这两者实在太像了,我们可以欺骗一下编译器,看下面的代码:

#include<stdio.h>
void test(){static int a=1;printf("%d",a++);
}
void test2(){extern int a;printf("%d",a);
}
void main(){test();test2();
}

这个代码连接时一定不能通过,原因是test2中的a根本没有定义.由于static int a只存在于test内,test2无法访问到.但是上面的代码却可以汇编通过(关键代码如下):

test:
.LFB0:movl    a.1933, %eaxleal    1(%eax), %edxmovl    %edx, a.1933subl    $8, %esppushl   %eaxpushl   $.LC0call    printftest2:
.LFB1:movl    a, %eaxsubl    $8, %esppushl   %eaxpushl   $.LC0call    printfa.1933:.long   1

可以看到static int a被编译器在test中别名为了a.1933,而test2并不知道这一点.因此我们可以手动修改test2让它知道这一点.即把a别名成a.1933,这样再编译执行,这样可以顺利输出12.而此时的static int a完全被改造成了全局变量.

C语言函数内static关键字 疑惑相关推荐

  1. javaScript内置函数(内置函数,内置关键字)

    javaScript内置函数(内置函数,内置关键字)js的内置对象是js自带,封装了一些常用的方法.常用的js内置对象有:String,Date,Array,Math等:js内置函数是浏览器内核自带的 ...

  2. 变量是否在数组内c语言,函数内创建的数组在调用后,是否就不存在

    函数内创建的数组在调用后,是不是就不存在 本帖最后由 test_lockxxx 于 2014-04-23 09:31:06 编辑 第1种写法: char *getABC() { char str[10 ...

  3. c语言函数内判断嵌套常见错误,c语言不等于(c语言多个if函数怎么嵌套)

    其实我想问的是!=和==!有区别吗?我测试了一下,好像一样啊... 初学. 不等于符号就是 != != 是逻辑运算符,这个符号一般不适用于字符串的比较 != a为变量,用if语句检测a(不等于,大于, ...

  4. C语言static关键字修饰变量及函数时的用法和原理

    目录 一.static关键字修饰局部变量 二.static关键字修饰全局变量 三.static关键字修饰函数 一.static关键字修饰局部变量 在内存中,往往将其分为三个区块,栈区,堆区,静态区.C ...

  5. C语言之static关键字详解

    目录 前言: 一.几个概念 1.变量 2.局部变量和全局变量 3.变量的作用域 4.变量的生命周期 二.static关键字的作用 三.static关键字修饰局部变量 四.static关键字修饰全局变量 ...

  6. 从内存分配角度分析c和java里的static 关键字.

    即使作为Java的初学者, 对this 和 static 这两个关键字都不会陌生. 其实也不难理解: this 关键字:  指的是对象的本身(注意不是类本身)  跟.net 语言的Me 关键字类似. ...

  7. C++ static关键字

    C++ static关键字 static关键字可用于声明全局范围.命名空间范围和类范围的变量和函数. 静态变量还可在本地范围声明. 先介绍几个概念: 静态持续时间,在程序启动时分配对象或变量,并在程序 ...

  8. C/C++中static关键字用法汇总

    1. 函数内static局部变量:变量在程序初始化时被分配,直到程序退出前才被释放,也就是static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期.多次调用,仅需一次初始化. 2. ...

  9. c语言编程怎么自学网,c语言函数

    知识点:<c语言函数> 收集:胥僖涎 编辑:栀子花女孩 本知识点包括:1.C语言中有没有求绝对值的函数啊?谢谢! 2.关于C语言函数的声明,怎么理解能简单点 3.C语言中平方根的函数是多少 ...

最新文章

  1. vs2017报错 popen pclose
  2. gdi画平滑直线_石膏几何体不会画?那是你没有画过这些,学会画石膏很简单,收藏...
  3. 三菱st语言编程实例_LD、FBD、IL、ST、SFC、CFC六种编程语言的特点
  4. itextPdf~将PDF页面大小转为A4格式
  5. xshell更改背景颜色,解决乱码问题及更改字体及字体大小
  6. STM32那点事(2)_时钟树(中)
  7. 2017.9.28 降雨量 思考记录
  8. 谈MicroMessageTest的开始创建
  9. 【leetcode❤python】Intersection of Two Arrays
  10. 判断闰年的c语言程序_身为程序员还记得C语言经典算法(附带答案)吗?
  11. Android打造自定义通用popWindow
  12. 新浪微博开放平台开发-android客户端(1)
  13. 计算机职业资格证学什么,计算机职业资格证书有哪些
  14. 深度装N卡LINUX驱动 性能怎么样,讲解Deepin 20开源Nouveau和闭源NVIDIA驱动,附装闭源N卡驱动的方法...
  15. Java控制excel,word文档只读模式
  16. UGUI源代码之Image-Sliced模式
  17. AcWing 95. 费解的开关(推理)
  18. 积分使用及有效期管理
  19. LeetCode刷题记录(一)
  20. shell脚本中for循环及while循环写法

热门文章

  1. spring cloud config笔记
  2. access导入链接快还是导入表快_Go 语言设计哲学之十三:理解包导入路径的含义...
  3. 心电图心电轴怎么计算_心电图导联及心电轴
  4. linux 换行符_一个linux帮你做高效数据统计
  5. Mysql Too many connections解决方法
  6. linux如何在a休息时运行b,Linux下如何优雅地修正命令?
  7. oracle sql 调试,关于Oracle和SQL存储调试和出错处理
  8. 算法导论学习笔记 第6章 堆排序
  9. 60 个神级 VS Code 插件!
  10. 大一新生开发的小工具火了,网友:我好菜