【总结】static和extern和const以及定义与声明

一.C语言中的static关键字

    在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。

    (1)修饰局部变量

    一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。

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

    如:

复制代码
#include<stdio.h>

void fun()
{
static int a= 1;
a++;
printf( " %d\n ",a);
}

int main( void)
{
fun();
fun();
return 0;
}
复制代码

    程序执行结果为: 2

                  3

   说明在第二次调用fun()函数时,a的值为2,并且没有进行初始化赋值,直接进行自增运算,所以得到的结果为3.

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

   (2)修饰全局变量

   对于一个全局变量,它既可以在本源文件中被访问到,也可以在同一个工程的其它源文件中被访问(只需用extern进行声明即可)。

   如:

   有file1.c

   int a=1;

     file2.c

   #include<stdio.h>

   extern int a;

   int main(void)

   {

      printf("%d\",a);

        return 0;

   }

  则执行结果为 1

 但是如果在file1.c中把int a=1改为static int a=1;

 那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。

   (3)修饰函数

   用static修饰函数的话,情况与修饰全局变量大同小异,就是改变了函数的作用域。

二.C++中的static

   在C++中static还具有其它功能,如果在C++中对类中的某个函数用static进行修饰,则表示该函数属于一个类而不是属于此类的任何特定对象;如果对类中的某个变量进行static修饰,表示该变量为类以及其所有的对象所有。它们在存储空间中都只存在一个副本。可以通过类和对象去调用。对于静态成员函数,只能访问静态成员函数和静态成员变量,不能访问非静态成员函数或者变量。

三.extern关键字

   在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
   在上面的例子中可以看出,在file2中如果想调用file1中的变量a,只须用extern进行声明即可调用a,这就是extern的作用。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间。

   在C++中extern还有另外一种作用,用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。

 

static extern const 静态全局变量与全局变量的区别

static:和extern是用来设置作用域的 
const:设置变量只可以被读,不可以被修改

static:

用static修饰的变量,在其所限定的作用域中只会有一分内存

1:在一个函数内部:说明是一个静态局部变量,

不管这个函数被调用多少次,这个static修饰的变量只会有一分内存,也就是说当这个变量多次被修改,都是在上一次基础上修改,不会从头再来

2:在一个文件内部,函数外部:静态全局变量

该文件中的函数都可以访问到,并且不同函数在对该变量修改时都是在上一个函数修改的基础上修改的

静态全局变量和非静态全局变量的区别

static 限制了变量的作用域只在该文件里,所以加上static在别的文件中国定义一个相同的static没有问题 
没有static修饰的全局变量,要是在不同文件中定义了相同的变量名,程序会报错

extern:外部变量

用extern修饰的变量,可以被其他类所访问,凡是引用了extern所修饰的变量的头文件,那么就可以使用该变量。

但是要注意因为static修饰的不在全局符号表中,所以不用区分变量名
extern修士的在全局符号表里面,所以要区分。
  • 1
  • 2

const:一个变量用const修饰,说明该变量不可以被修改

混搭

1:static和const

static NSString *const indentifier = @"hello";
  • 1

相当于一个文件中的宏定义

2:extern和const

在.h文件中

extern NSString *const hello;
  • 1

在.m文件中赋值

NSString *const hello = @"world";
  • 1

可以用于发送通知,这样就不用知道name,只需要使用这个变量就可以了

补充

在iOS开发中的一种编程技巧:多用类型常量,少用#define预处理命令

static限制了变量的作用域,但是#define没有,如果我们仅仅想在一个文件内部使用一个常量,而不影响其他的文件的宏,如果用define,那么所有导入了该文件的那些文件中要是有一个相同的变量,那么这些变量都会被替换 
static 形式的常量定义,可以知道其类型,代码可读性好 
const的修饰使得该变量在修改会保存,确保其不会被修改,但是#define却不会,值可能会被修改

 

定义和声明以及extern、static关键字

1. 定义只能进行一次,声明可以多次。
2. 变量定义是为变量分配存储空间,也可以初始化,不初始化的定义如:int i;
3. 声明是表明变量的类型和名称,因此定义也是声明。
4 . 没有初始化的时候,有extern表示这是声明,不是定义,不分配存储空间,如:extern int i;
5. 但是如果有初始化时,即使加了extern也是定义,如:extern int i = 0,这个时候i只能在函数外部定义。
6. 没有extern的声明都可以看做是定义,如第二条。
 
具有文件作用域的变量或函数,其链接属性默认是extern的,使用static可将(而且是仅仅这种情况下才能改变)缺省链接属性为extern声明的链接属性改为源文件私有的链接属性,即internal。
在函数内部,如果在变量声明中加入extern,则指定改变量的链接属性为external,这样该函数就可以访问在其他源文件声明的外部变量了。
正常来说,只有在声明的时候,加上static或extern才是必须的,但为了人为理解方便,建议是在一个地方定义变量以后(最好别把定义放在头文件里),并在使用这个变量的其他源文件处的声明中加上extern关键字,增加易读性。
 
extern关键字用于源文件中一个标识符的第一次声明时,它指定该标识符具有external链接属性,但是如果它用于该标识符第二次或以后的声明时,它并不会改变第一次声明所指定的链接属性,如:
static int i;
int func()
{
    int j;
    extern int k;
    extern int i;
……
}
函数内部的i并不改变链接属性为internal的i的链接属性。
 
举例说明
对于extern关键字来说,比较常用的场景是:
a.c需要引用b.c中定义的全局变量(注意是全局变量,假设为i),需要在a.c中,先声明:extern int i;然后就可以直接使用i了。而i的定义则在b.c中,且不需要加extern关键字,因为默认的链接属性已经是extern了,更确切地说,只在声明中使用extern即可(结合第四条理解)。

另外一种选择,可以在a.h中以extern来声明b.c中的那个变量i。这两种方法都可以,但是在大型软件中,还是第一种方法效率更高(加速程序编译过程的预处理的速度)。

相关内容见《C和指针》41页

 

具体声明定义区别

  •              声明就是指给除了当前变量或者函数,或者类什么的名字,不给其中的内容,就是先告诉你有这样一个什么类型的变量或者函数,但是这个变量或者函数的具体信息却是不知道的。就好比跟你介绍一个人的时候,声明就是只告诉你这个人叫什么,但是缺不给你说这个人到底怎么样,他有哪些优点,缺点,喜好问题是什么的。

  •           定义就不一样了,定义直接告诉你了所有的东西,这个变量是什么,这个函数是什么功能,这个类里面包含了什么东西。很具体的说明。

  • 当然一般对于变量来说,我们不怎么区分声明或者定义之类的,一般没有人去说我要声明一个变量,然后定义这个变量什么的。要说都是直接说定义变量。

  • 声明一般都是对函数或者类来说的,声明在前,定义在后。

  • int a;可以说是声明,广泛的说是定义一个变量a,也不算错。

 

 

 

C++声明和定义的区别 收藏

 

《C++Primer》第四版 2.3.5节中这么说到:

①变量定义:用于为变量分配存储空间,还可为变量指定初始值。程序中,变量有且仅有一个定义。

②变量声明:用于向程序表明变量的类型和名字。

③定义也是声明:当定义变量时我们声明了它的类型和名字。

④extern关键字:通过使用extern关键字声明变量名而不定义它。

 

1.定义也是声明,extern声明不是定义,即不分配存储空间。extern告诉编译器变量在其他地方定义了。

例如:extern int i; //声明,不是定义

             int i; //声明,也是定义           

 

2.如果声明有初始化式,就被当作定义,即使前面加了extern。只有当extern声明位于函数外部时,才可以被初始化。

例如:extern double pi=3.1416;  //定义

 

3.函数的声明和定义区别比较简单,带有{ }的就是定义,否则就是声明。

例如:extern double max(double d1,double d2);  //声明

 

4.除非有extern关键字,否则都是变量的定义。

例如:extern int i; //声明

             int i; //定义          

 

 

程序设计风格:

    1. 不要把变量定义放入.h文件,这样容易导致重复定义错误。

    2. 尽量使用static关键字把变量定义限制于该源文件作用域,除非变量被设计成全局的。

    3. 可以在头文件中声明一个变量,在用的时候包含这个头文件就声明了这个变量。

 

总结:

变量在使用前就要被定义或者声明。

在一个程序中,变量只能定义一次,却可以声明多次。

定义分配存储空间,而声明不会。

 

       C++程序通常由许多文件组成,为了让多个文件访问相同的变量,C++区分了声明和定义。

        变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义。

        声明(declaration)用于向程序表明变量的类型和名字。定义也是声明:当定义变量的时候我们声明了它的类型和名字。可以通过使用extern声明变量名而不定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern。

        extern声明不是定义,也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。

        只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。

        任何在多文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义,使用该变量的其他文件则包含该变量的声明(而不是定义)。

 

  --------------------------------------------------------------------头文件中定义与声明

 

注意头文件中不可以放变量的定义!!!一般情况下头文件中只放变量的声明,因为头文件要被其他文件包含(即#include),如果把定义放到头文件的话,就不能避免多次定义变量,C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。

不过有三个例外,一下三中实体的定义也可放到头文件中。

1.值在编译时就已知的const 变量的定义可以放到头文件中

如:const int num(10);

2.类的定义可以放到头文件中

3.inline 函数

这三个实体可以定义在多个源文件中,只要在每个源文件中的定义相同。

 

/--------------------------------------------------------------------头文件中定义与声明

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值