前言
在C语言中,static
是一个关键字,它可以用在不同的上下文中,赋予变量或函数不同的意义。static
关键字主要用于控制变量的存储期和可见性,以及函数的链接性。下面是 static
关键字的主要作用原理与用途:
局部静态变量
当 static
修饰局部变量时(即在函数内部定义的变量),它会改变该变量的存储期,但不会改变其作用域。局部静态变量只在其定义的函数内部可见,但它的生命周期贯穿整个程序运行期间,而不是在函数调用结束后就销毁。这意味着,即使函数执行完毕,局部静态变量的值也会被保留,并在下一次函数调用时继续使用。
一般未定义储存类型的变量会自动的定义为auto储存类型(储存类型有四种,auto,static,extern,register)auto的存储位置在栈(栈是由编译器申请,由编译器释放),使用的时候临时申请空间,使用完就撤销保存,而使用static关键词进行修饰后它的储存位置就改到了静态区初始化后存在数据段,它的生命周期延长至直到结束。
参考下面的代码示例来理解;
使用关键词static进行修饰
全局静态变量
当 static
修饰全局变量时(即在函数外部定义的变量),它会限制该变量的链接性(linkage),使其只在定义它的文件内部可见,对其他文件不可见。这有助于避免不同文件中的全局变量名冲突。
当一个全局变量在一个源文件中定义后,想要在其他源文件中进行使用时,需要在需使用的源文件中加入一个链接告诉编译器此变量已在其他文件中定义,你去其他文件中找吧,即extern 数据特征 变量名(例 extern int a)告诉编译器整形变量a在其他文件定义了。如果使用static关键词进行修饰后,就限制此变量的作用域只在本源文件,不会作用其他源文件出现的同样变量,限制了该变量的链接性。
静态函数
当 static
修饰函数时,它会将函数的链接性更改为内部链接(internal linkage),意味着该函数只能在其定义的文件内部被调用,其他文件无法链接到这个函数。这有助于封装,并防止函数名在不同文件间的冲突。
与全局静态变量相似,其作用是限制了其函数的作用域,只可在自己的源文件中使用。
C++扩展
修饰类成员变量:
在C++中,当static
修饰符用于类成员变量时,这个成员变量就不再属于类的任何特定对象实例,而是属于类本身。这意味着所有该类的对象共享这个static
成员变量的一个实例。这个特性使得static
成员变量成为在类的所有对象之间共享数据的理想方式。
以下是一些关于static
修饰类成员变量的关键点:
-
存储期:
static
成员变量的存储期与程序的运行期相同,即它们在程序开始时被分配内存,并在程序结束时被销毁。 -
初始化:
static
成员变量必须在类定义之外进行初始化,通常在类的实现文件(.cpp
文件)中进行。如果static
成员变量是整型或枚举类型,并且没有被显式初始化,那么它会被自动初始化为0。对于其他类型,如果没有显式初始化,则结果是未定义的。 -
访问:
static
成员变量可以通过类名直接访问,而不需要创建类的对象。但是,在类的成员函数内部,可以像访问普通成员变量那样通过this
指针(尽管实际上并不需要使用this
,因为static
成员变量与任何特定对象无关)或者简单地通过成员变量名来访问它。在类外访问static
成员变量时,必须通过类名和作用域解析运算符::
来访问。
修饰成员函数:
在C++中,当static
修饰符用于成员函数时,这个成员函数就不再与类的任何特定对象实例相关联。这意味着你不能在static
成员函数中访问类的非静态成员变量(除非通过对象实例的指针或引用显式传递),因为非静态成员变量是依赖于具体对象实例的。static
成员函数可以访问类的其他static
成员变量和成员函数。
static
成员函数的主要用途包括实现与类相关的工具性功能,这些功能不需要访问类的非静态成员。它们也常用于访问或修改类的static
成员变量。
以下是一些关于static
修饰成员函数的关键点:
-
访问限制:由于
static
成员函数不与任何对象实例相关联,因此不能在static
成员函数内部使用this
指针。this
指针用于访问调用它的对象的成员,但在static
成员函数中没有这样的对象。 -
调用方式:
static
成员函数可以通过类名直接调用,也可以通过类的对象实例调用(尽管这样做在逻辑上可能不太直观,因为static
成员函数不依赖于任何特定对象)。 -
参数传递:如果
static
成员函数需要访问类的非静态成员,它必须接受一个指向类对象的指针或引用作为参数。