浅析 static、external、const

-------------------------------------const--------------------------------

      const关键字,很多人想到的可能是const常量,其实关键字const并不能把变量变成常量!

在一个符号前加上const限定符只是表示这个符号 不能被赋值。也就是它的值对于这个符号来说是只读的,但它并不

防止通过程序的内部(甚至是外部)的方法来修改这个值。也就是说 const变量是只读变量,既然是变量那么就可以

取得其地址,然后修改其值。看来const也是防君子不防小人!


const 使用情况分类详析


  1、const的普通用法


      const  int n = 20 ;

      意思很明显,n是一个只读变量,程序不可以直接修改其值。

      这里还有一个问题需要注意,即如下使用:int a[n];在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而n只是一个变量。


  2、const用于指针


    const int* p1 ;        //指针指向的内容不能用指针改变

    int  const *p2;        //指针指向的内容不能用指针改变                     

    int* const  p3 ;       //指针的指向不能改变

    const int *const p4 ;  //指针的指向不能改变,同时指针的内容不能通过指针改变

    进一步解析:前面两种p1、p2指针 指向的对象是只读的。const是一个左结合的类型修饰符,它与左侧的类型一起为一个类型修饰符,所以,int const 限定*p2,(p1也是同样的)。int* const 限定p3,而不是限定*p3。

    这里有一个简便的区分方法:“就近原则”, 去掉类型后,const离哪个(‘*’p(指针))近就修饰哪个


  3、const用于函数的地址传递参数


     void fun(const int *p);

    这种形式通常用于在数组形式的参数中模拟传值调用。也就是相当于函数调用者声称:"我给你一个指向它的指

针,但你不能去修改它。"如果函数编写者遵循了这个约定,那么就相当于模拟了值传递。这也是const最有用之处

了:用来限定函数的形参,这样该函数将不会修改实参指针所指的数据。这里注意了,是函数不应该去修改而不是不

能修改。


   4、const用于限定函数的返回值


      const int fun();

      上述写法限定函数的返回值不可被更新,当函数返回内部的类型时,已经是一个数值,当然不可被赋值更新,所

以,此时const无意义,最好去掉,以免困惑。当函数返回自定义的类型时,这个类型仍然包含可以被赋值的变量成

员,所以,此时有意义。


const用法:

       定义常量,修饰指针、函数的输入参数和返回值,简单说const表示只读的意思,本质上来说它只是在全局数据

段或者栈中定义的是一个只读的常量,不是真正位于字符串常量区。Const的目的是为了产生高质量的代码,提高代

码的可读性,同时保护好不能被任意改变的内存,从而降低Bug产 生的概率。


-------------------------------------extern------------------------------------------------


基本解释及用法

      extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。通过这种行为它告诉编译器:该变量/函数的定义已经存在在某个地方了,让编译器到其他的模块去寻找它的定义。此外extern也可用来进行链接指定。

     也就是说extern有两个作用:第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在

编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的。

      第二,当extern不与"C"在一起修饰变量或函数时。

      如在头文件中:extern int i;  //它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可

以在本模块或其他模块中使用,记住它是一个声明不是定义!


-------------------------------------static------------------------------------------------


当一个进程的变量被声明为static之后,它的中文名叫静态变量。 使用时可以改变其值。它只在定义它的源

文件内有效,其他源文件无法访问它,程序开始时分配空间,结束时释放空间,默认初始化为0。所以,普通变

量穿上static外衣后,它就变成了新娘,已心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。



static用法分析


1、修饰变量

     A、修饰局部变量

         一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如

果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注

意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,

其仍然是一个局部变量,作用域仅限于该语句块。


在用static修饰局部变量后,该变量只在初次运行时进行初始化工作,且只进行一次。 


例如:

#include<stdio.h>

void funTest()
{
static int a = 1;
a++;
printf("%d ", a);
}
int main()
{
funTest();
funTest();
return 0;
}


输出结果: 2 , 3


解析:说明第二次电泳funTest函数时,a已经有了值(为2),并且没有进行初始化赋值,直接进行自增运算,所以

得到的结果为3.

      另外,对于静态局部变量如果没有进行初始化的话,对于整形变量系统会自动对其赋值为0,对于字符数组,会自动赋值为'\0'。

     B、修饰全局变量

         静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源文件内有效,其他源文件无法访问它。


   例如:

Test.h

#include<stdio.h>
void PrintStr();

test1.c      在这里定义一个全局变量 ,看是否其他源文件是否能访问

#include"Test.h"
static int a = 0;
void PrintStr()
{
	printf("%d ", a);
}


test2.c   在这里我们测试看看

#include"Test.h"
int main()
{
	 PrintStr();
	 printf("%d ", a);

}

编译,报错如下:

       error C2065: “a”: 未声明的标识符

如果将 test2.c 修改成这样:

 

#include"Test.h"
int main()
{
	 PrintStr();
	// printf("%d ", a);

}

编译成功,完美运行生气


解析: test1.c中的a就是一个静态全局变量,它可以被同一文件中的 PrintStr调用,但是不能被不同源文件中的test2.c调用。

    


2、修饰函数


        在函数前面添加static 后使得函数的访问域仅仅为其所定义的函数。


测试如下:


Test.h     //添加两个函数,一个加上static   另一个不添加

#include<stdio.h>
static void PrintStr();
void  funTest();

test1.c    //在这里定义两个函数

#include"Test.h"
 int a = 0;
 static void PrintStr()
{
	printf("%d ", a);
}
 void  funTest()
 {
		
	 printf("%d ", a + 1);
 }
test2.c        //通过这个源文件,看是否能编译成功


#include"Test.h"
int main()
{
	 PrintStr();
	 funTest();
	 return 0;

}

编译结果: error C2129: 静态函数“void PrintStr()”已声明但未定义


将test2.c修改成这样:

#include"Test.h"
int main()
{
	// PrintStr();
	 funTest();
	 return 0;
}


解析:  funTest和PrintStr都是在test1.里定义,但PrintStr前面添加了ststic,限定了它的使用范围,只能在当前源文件处使用


对于 const 、extern、static  还需要添加的,希望各位指点可怜


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值