首页 > 其他分享 >static关键字的作用

static关键字的作用

时间:2024-06-17 23:22:17浏览次数:19  
标签:函数 int 源文件 关键字 static 全局变量 链接 作用

分析C语言static关键字的作用

目录

  • 先来看一个案例
#include <stdio.h>

int a=5;
void show_val(void)
{
    int b=3;
    static int c=2;
    a+=5;
    b+=5;
    c+=5;
    printf("a = %d,b = %d,c = %d\n",a,b,c);
    c = b;
}
int main(void)
{
    int b=0;
    static int c;
    a += 3;
    show_val();
    b += 3;
    show_val ();
    return 0;
}

img

第一次打印结果:a = 13,b = 8,c = 7

第二次打印结果:a = 18,b = 8,c = 13

  • 为什么会有这样的结果呢?主要受static关键字的影响,下面就来分析static关键字的作用。

1.静态存储期(局部变量使用static时)

1.当static关键字用于函数内的局部变量时,它改变了该变量的存储期。通常,函数内的局部变量具有自动存储期,这意味着它们在进入函数时创建,在离开函数时销毁。

2.但是,当局部变量被声明为static时,它获得了静态存储期,这意味着该变量在程序开始时分配内存,在程序结束时释放内存。
3.静态局部变量的初始值只会在第一次进入函数时设置,之后调用函数时不会再次设置。因此,静态局部变量可以用来跟踪函数被调用的次数,或者记住跨函数调用之间的某些状态。

//例如:
void Function() {  
    static int count = 0;  
    count++;  
    printf("Function has been called %d times\n", count);  
}  
// 多次调用 counterFunction 会显示递增的计数
int main()
{
    for(int i = 0;i < 5,++i)
    {
        function();
    }
    return 0;
}

img

2.静态全局变量

1.全局变量可以使用 static 关键字进行修饰。但是,当我们在全局作用域(即文件级作用域)中使用 static 修饰一个变量时,它的意义与在函数内部(局部变量)使用 static 修饰变量时有所不同。

2.我们知道,当在函数内部使用 static 修饰一个变量时,该变量在函数调用之间保持其值。这意味着它只会在第一次调用该函数时被初始化,并在随后的函数调用中保持其值。

3.当在全局作用域中使用 static 修饰一个变量时,该变量具有内部链接。这意味着该变量只在其定义的文件中可见,对其他文件是不可见的。这通常用于限制全局变量的可见性,防止其他文件意外地访问或修改它。

因此,静态全局变量的特性是:

(1)它的作用域是全局的,意味着在程序中的任何函数内部都可以访问它(只要它们有正确的访问权限)。
(2)它的生命周期是整个程序的执行期间,从程序开始到程序结束。
(3)由于它是 static 的,所以它的可见性被限制在定义它的文件内部。这意味着如果你试图在另一个源文件中访问这个静态全局变量,你将无法做到(除非使用某种特殊的链接技术,如外部声明)。

//例如:
// file1.c  
static int Val = 10;  
  
void func()
{  
    printf("%d\n", Val);  
}  
  
// file2.c  
//...
    
// 这里不能访问 Val,因为它在 file1.c 中是 static 的
//在这个例子中,Val 只在 file1.c 中可见,因此 file2.c 不能访问它。

1.注意:在一个C语言工程项目中,我们往往有很多的.c源文件。如果两个或多个.c源文件定义了相同名字的全局变量(即具有外部链接的变量),那么这会导致链接器错误,因为链接器会在试图将多个目标文件合并成一个可执行文件或库时,发现存在名称冲突的全局符号。

2.因为每个.c源文件在编译后都会生成一个目标文件(比如.o文件),这些目标文件包含了源文件中的函数和全局变量的信息。当链接器试图将这些目标文件合并成一个可执行文件时,它会查找所有全局符号的定义,并确保每个符号只被定义一次。因此如果两个或多个目标文件定义了相同的全局变量,链接器会报告一个错误,指出存在重复定义的符号。因此避免在多个.c源文件中使用相同的变量名尤为重要,(即使全局变量的类型不同,但只要它们的名字相同,并且都是具有外部链接的全局变量,那么在不同的.c源文件中定义它们仍然会导致链接器错误)。

如下是避免这种情况的方法:

(1)使用不同的变量名:这是最简单的方法,只需确保每个.c文件中的全局变量都有唯一的名称。

(2)使用static关键字:在全局变量的声明前添加static关键字可以将其作用域限制在单个源文件内。这样,即使两个或多个源文件都包含了相同名称的static全局变量,链接器也不会报告错误,因为这些变量实际上是在不同的作用域中定义的。

(3)使用外部变量声明:在一个.c文件中定义全局变量,并在其他需要使用这个变量的.c文件中使用extern关键字声明它。这样,所有的.c文件都共享同一个全局变量的定义。(extern关键字可以声明一个函数或者一个变量的属性是外部可链接的,意味着可以被外部文件调用。)

//例如:
// file1.c  
int val = 10; // 定义全局变量  
 
// file2.c  
extern int val; // 声明全局变量,但不定义它  
 
// 然后在file2.c中可以使用val

3.static与函数一起使用

static与函数一起使用时,它主要有两个主要用途:文件作用域或内部链接。

当你在一个C源文件的文件作用域(即在所有函数之外)中声明一个函数为static时,这个函数的链接属性会被改变为内部链接。这意味着该函数只能在声明它的源文件中被访问,而不能从其他源文件中被链接或访问。
这有助于隐藏实现细节,使得库的实现者可以提供某些功能,而不需要暴露这些功能的接口给库的最终用户。

//例如:
static void function()
{  
// ......  
}  
// 其他源文件不能调用function

标签:函数,int,源文件,关键字,static,全局变量,链接,作用
From: https://www.cnblogs.com/lwj294/p/18253428

相关文章

  • Python - class Method and static Method
    Themethodsinaclassareassociatedwiththeobjectscreatedforit.Forinvokingthemethodsdefinedinsidethemethod,thepresenceofaninstanceisnecessary.Theclassmethodisamethodthatisalsodefinedinsidetheclassbutdoesnotneedanyob......
  • switch 语句能否作用在 byte 上;作用在 long 上;作用在 String 上?
    在Java中,switch语句可以作用于多种类型,具体情况如下:可以作用于byte类型:byte类型可以隐式转换为int,因此可以用作switch语句的条件表达式。publicclassSwitchByteExample{publicstaticvoidmain(String[]args){byteb=2;swit......
  • 超详细Python教程——作用域
    学习过Java的同学都知道,Java的类里面可以给方法和属性定义公共的(public)或者是私有的(private),这样做主要是为了我们希望有些函数和属性能给别人使用或者只能内部使用。通过学习Python中的模块,其实和Java中的类相似,那么我们怎么实现在一个模块中,有的函数和变量给别......
  • 数据可视化在智慧物流中发挥了什么作用?
    数据可视化在智慧物流中发挥了至关重要的作用,成为优化物流管理、提升效率和改善客户体验的关键工具。在现代物流行业中,面对海量数据的挑战,数据可视化技术通过将复杂数据转化为直观的图表、图形和仪表盘,帮助企业和管理者更有效地理解、分析和利用信息,从而做出更明智的决策。首先,......
  • 快速解决:使用Mindspore框架时报错!!libgomp-6e1a1d1b.so.1.0.0: cannot allocate memory
    前言:最近在用ms跑大模型,需要做好多步骤,遇到报错跟大家一起分析一下吧刚开始转换权重就遇到了下述报错:ImportError:/root/anaconda3/envs/MS/lib/python3.9/site-packages/torch/lib/../../torch.libs/libgomp-6e1a1d1b.so.1.0.0:cannotallocatememoryinstaticTLSblo......
  • [JS] 动态执行JS与修改词法作用域
    相关可行的操作eval:同步执行,当前作用域;setTimeout:异步执行,全局作用域;第1个参数可以传入函数对象,也可以传入字符串,即要执行的代码。script:同步执行,全局作用域;创建script标签,并设置innerHTML为要执行的代码。Function:同步执行,全局作用域。Function构造函......
  • 回调函数的代码示例及其意义与作用
    回调函数的代码示例及其意义与作用在C语言中,回调函数(CallbackFunction)同样具有重要的意义和作用。尽管C语言没有像JavaScript或Python那样内置的高级异步处理机制,但回调函数在C语言中仍然被广泛应用,尤其是在以下场景:事件驱动编程:当某个事件发生时(如定时器到期、用户输入、文......
  • 生成式人工智能在军事中的作用
    2023年以来,以大语言模型为代表的生成式人工智能技术取得突破性进展,新产品、新技术陆续亮相,引发新一轮人工智能发展热潮。随着生成式人工智能系统在商用领域的成功应用,美军意识到生成式人工智能在指挥控制、情报分析、作战规划、辅助决策等军事领域具有巨大的应用潜力,因此已经开......
  • 简述回调函数的意义和作用
    回调函数是一种在程序中广泛使用的机制,它的意义和作用主要包括以下几个方面:异步操作:在一些需要异步执行的任务中,如网络请求、文件读写等,回调函数可以在任务完成后被调用,以便进行后续的处理。这样可以避免阻塞程序的执行,提高程序的响应性和效率。事件处理:回调函数可以用于处理各......
  • 是否可以从一个static方法内部发出对非static方法的调用
    不可以直接从一个static方法内部发出对非static(即实例)方法的调用。static方法属于类本身,而非static方法则属于类的实例(对象)。由于static方法不依赖于类的任何特定实例,因此它不能直接访问非static方法或实例变量,因为这些方法和变量都需要类的实例来调用或访问。但是,有几种方法......