菜单开关

周梦康 发表于 2017-09-27 1779 次浏览 标签 : CC语言快速入门

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

从作用域上来说,C语言可以定义4种不同的变量:全局变量,静态全局变量,局部变量,静态局部变量。

下面仅从函数作用域的角度分析一下不同的变量,假设所有变量声明不重名。

  • 全局变量,在函数外声明,例如,int gVar;。全局变量,所有函数共享,在任何地方出现这个变量名都是指这个变量。 除非在函数内部被重新声明定义,如下例代码。
  • 静态全局变量,例如:static sgVar;。所有函数共享,但是这个会有编译器的限制,算是编译器提供的一种功能。
  • 局部变量,例如函数/块内的int var;。不共享,函数的多次执行中涉及的这个变量都是相互独立的,他们只是重名的不同变量而已。
  • 局部静态变量,函数中的static int sVar;。本函数内共享,函数的每一次执行中涉及的这个变量都是这个同一个变量。

全局变量

int gVar = 0; // 全局变量
void gVarInr();

int main(int argc, char const *argv[]) {

    int gVar = 10; // 局部变量

    gVarInr();
    printf("gVar is %d\n",gVar); // 10

    gVarInr();
    printf("gVar is %d\n",gVar); // 10

    return 0;
}

void gVarInr()
{
    gVar++;
    printf("gVar is %d\n",gVar); // 1 2
}

打印结果

gVar is 1
gVar is 10
gVar is 2
gVar is 10

全局静态变量

全局变量之前再冠以 static 就构成了静态的全局变量。

存储方式

全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。

作用域区别

这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。

实例演示

文件1:a.c代码

#include <stdio.h>

int a = 10;

文件2:b.c代码

#include <stdio.h>
extern int a;

int main(int argc, char const *argv[]) {
  printf("%d\n", a);
  return 0;
}

b.c使用 extern 引入a.c里面定义的全局变量a。编译

$ gcc a.c b.c -o test
$ ./test
10

修改为全局静态变量

#include <stdio.h>

- int a = 10;
+ static int a = 10;

再编译则提示

$ gcc a.c b.c -o test
Undefined symbols for architecture x86_64:
  "_a", referenced from:
      _main in bbb-616389.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

扩展:函数和静态函数也与之类似,函数默认是全局的,加了static之后,其作用域就只是本文件了。

局部变量

#include <stdio.h>

void varInr();
int main(int argc, char const *argv[]) {
    
    varInr();
    varInr();

    return 0;
}

void varInr()
{
    int var = 0;
    var++;
    printf("var is %d\n",var);
}

打印结果

var is 1
var is 1

这个大家都很熟悉了

局部静态变量

#include <stdio.h>

void varInr();
int main(int argc, char const *argv[]) {

    varInr();
    varInr();

    return 0;
}

void varInr()
{
-   int var = 0;
+   static int var = 0;
    var++;
    printf("var is %d\n",var);
}

打印结果

var is 1
var is 2

上面几种作用域都是从函数的角度来定义作用域的,可以满足所有我们对单线程编程中变量的共享情况。
现在我们来分析一下多线程的情况。在多线程中,多个线程共享除函数调用栈之外的其他资源。 因此上面几种作用域从定义来看就变成了:

  • 全局变量,所有函数共享,因此所有的线程共享,不同线程中出现的不同变量都是这同一个变量。
  • 静态全局变量,所有函数共享,也是所有线程共享。
  • 局部变量,此函数的各次执行中涉及的这个变量没有联系,因此,也是各个线程间也是不共享的。
  • 静态局部变量,本函数间共享,函数的每次执行涉及的这个变量都是同一个变量,因此是各个线程共享的。

这对我们后期的线程安全编程非常有用。http://www.php-internals.com/book/?p=chapt08/08-03-zend-thread-safe-in-php

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表