关键字static的用法

       在C语言或者面向过程的C++中,关键字static经常和变量、函数一起来定义静态变量(静态全局变量、静态局部变量)和静态函数。而静态变量、静态函数的用法经常让人和普通变量、普通函数产生混淆,因此决定对staticC语言和面向过程的C++中用法进行一次全面的分析总结。


1、静态全局变量

       “static +全局变量”就定义了一个静态全局变量。静态全局数据有以下特点:

      (1)未经初始化时,程序自动初始化为0;

      (2)在全局数据区分配内存

       静态全局变量包括后边的静态局部变量都是在全局数据区分配内存。一般情况下程序中新产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间。而全局数据区的数据并不会因为函数的退出而释放空间

      (3)作用域是定义它的文件

       全局变量可以在工程所有文件中共享使用,作用域是整个工程。在一个文件中定义的全局变量,可以在另一个文件中通过“extern+全局变量”的方式进行声明后使用这个变量。而静态全局变量只能在定义它的文件中使用,其他文件即使通过extern声明也不能使用。

       这样静态全局变量有一个好处:可以在需要的文件中随便定义,而不必考虑其他文件中是否有重名的变量从而造成冲突。


2、静态局部变量

       和静态全局变量的定义类似,“static +局部变量”就定义了静态局部变量。和静态全局变量类似,静态局部变量具有如下特点:

       (1)在全局变量区分配内存;

       (2)一般在声明处初始化,没有显式初始化时自动初始化为0;

       (3)在程序执行到声明处时首次初始化,以后不再进行初始化;

       静态局部变量的一个典型用法是:希望每一次调用时函数中的变量值能够保存。局部变量在栈区开辟内存,因此函数执行完成后,栈区内存被收回,局部变量也就失效。如果是全局变量呢?变量的值虽然可以保存,但是变量的作用域就不仅仅是函数内部了,也不再受函数的控制,会给程序的维护带来不便。静态局部变量作用域是定义它的函数,同时在全局变量区分配内存,正好完美解决这一问题。


3、 静态函数

       在函数的返回类型前加上static关键字,就把函数定义为静态函数。静态函数和普通函数的最主要区别是作用域。静态函数的作用域是定义它的文件,而普通函数的作用域是整个工程,别的文件通过extern声明这个函数后就可以使用。因此和静态全局变量类似,静态函数名可以防止不同文件中定义同名函数所带来的冲突。


4、static用法小结

       通过以上的分析总结,可知static的主要用法或特征有三点:初始0、持久和隐藏。

      (1)初始0

      主要针对静态全局变量和静态局部变量来说的。如果静态变量没有显式初始化,则系统默认把其初始化为0,且系统仅在声明处对其进行初始化一次。

      (2)持久

      此项也是主要针对静态全局变量和静态局部变量来说的。不管是静态全局变量还是静态局部变量均是在全局变量内存区开辟内存,因此其作用时间也就是程序的运行时间。变量的值能够持久保存,直至程序运行结束。

      (3)隐藏

       这也是static的最主要用途。static可以把变量和函数的作用域限制为定义变量的文件内,而其他文件则不可以使用或访问static定义的变量和函数。这样带来的好处是防止不同文件中定义同名变量或函数所带来的冲突。


5、使用static的一个实例

       在编写FPGA NIOS II的串口驱动程序中用到了静态函数。为了保持驱动函数的独立性,防止与其他文件中定义的函数重名,把与串口有关的函数定义为了静态函数。在uart.c中函数声明程序如下:


   


       在这里声明了uart_send_byteuart_send_stringuart_inituart_ISRset_baudrate等函数为静态函数,其作用域也就被限制于uart.c了,在其他文件中就不可以通过extern声明来使用这些函数了。我们可以通过以下的方法来解决其他文件中使用静态函数的问题。比如我们需要在主程序main.c中使用这些函数。


        


       如上图所示,我们在uart.h中定义一个UART_T类型的结构体。结构体成员是UART驱动程序中的关键参数和函数。定义一个名为uartUART_T类型的结构体变量,并用extern对这个变量进行声明,从而可以在其他文件中使用这个变量。如下图所示在uart.c文件中对结构体变量uart初始化。把uart_send_byteuart_send_stringuart_initset_baudrate等函数赋值给结构体中的函数成员。这样就可以通过访问结构体成员函数来调用uart.c中定义的静态变量了。比如:uart.send_string就是调用uart_send_string函数。


     

     



<think>嗯,用户想了解编程中关键字static用法和含义。首先,我需要回忆不同编程语言中static的不同应用。因为static在多种语言中都有出现,但具体用法可能不同。比如在C、C++、Java、C#中,static的作用域和生命周期管理是关键。而像JavaScript这样的语言,static可能用于类的方法或属性。 首先,用户可能没有明确说明是哪种语言,所以需要覆盖主要的几种情况。比如在C语言中,static用于函数内部的变量时,会延长其生命周期,使其在函数调用之间保持值不变。同时,在文件作用域中,static可以限制变量或函数仅在当前文件内可见。这可能和C++中的静态成员函数和变量有关联,C++中类的静态成员属于类本身,而不是实例。 然后,Java中的static用法和C++类似,用于类的成员,表示该成员属于类级别,所有实例共享。静态方法不能访问非静态成员,这点需要强调。此外,在Java中静态导入也是一个点,但可能用户更关注基础用法。 C#中的static和Java类似,但还有静态类,这种情况类只能包含静态成员,不能实例化。这部分可能需要提及。 JavaScript(ES6之后)的类中,static用于定义静态方法,这些方法只能通过类本身调用,而不是实例。比如Array.isArray这样的方法。 另外,用户可能对内存分配感兴趣,比如静态变量在内存中的位置,通常在程序的整个生命周期存在,存储在静态存储区。而局部静态变量虽然作用域受限,但生命周期是全局的。 还要考虑用户可能的常见误区,比如在C中函数内部static变量的初始化只进行一次,以及多线程环境下静态变量的线程安全问题。不过这可能超出基础用法的范围,但可以作为高级提示提及。 需要组织回答结构,分语言说明,并总结共同点。比如,static通常用于控制作用域、生命周期和共享性。同时,给出代码示例会更清晰,但用户提到行内数学表达式用$...$,但代码块应该用三个反引号。不过用户的问题是关于static的,可能不需要数学公式,但需要确保代码格式正确。 最后,生成相关问题,比如静态变量与全局变量的区别,静态方法的特点,不同语言中的差异,内存分配问题,设计模式中的应用等。这些问题可以帮助用户深入理解。 需要检查是否有遗漏的语言或用法,比如PHP中的static,或者在函数式编程中的使用,但可能用户主要关注主流面向对象语言。确保覆盖C、C++、Java、C#、JavaScript,并指出不同语言的可能差异。 总结:分点回答,按语言分类,说明每种情况下的用法,并给出示例代码。最后总结共同目的,并生成相关问题。</think>### 编程关键字 `static` 的用法与含义 `static` 是编程中常见的**关键字**,其具体含义和用法因语言而异,但核心思想通常围绕**作用域**、**生命周期**和**共享性**展开。以下是主要编程语言中的用法详解: --- #### 1. **C/C++ 中的 `static`** - **局部变量**(函数内部) 声明为 `static` 的局部变量会**保留值**,即使超出作用域也不会销毁,下次调用函数时仍可访问其值。生命周期与程序运行周期一致。 ```c void counter() { static int count = 0; // 只初始化一次 count++; printf("%d", count); } // 多次调用 counter() 输出:1, 2, 3... ``` - **全局变量/函数**(文件作用域) 使用 `static` 修饰全局变量或函数时,其作用域限制在**当前文件**内,避免与其他文件的同名符号冲突[^1]。 ```c static int internal_var = 42; // 仅本文件可见 ``` - **类成员(C++)** 静态成员属于**类本身**而非实例,所有对象共享同一份数据。静态方法只能访问静态成员。 ```cpp class MyClass { public: static int shared_value; // 类成员声明 static void printValue() { cout << shared_value; } }; int MyClass::shared_value = 0; // 类外定义 ``` --- #### 2. **Java/C# 中的 `static`** - **类成员** 静态变量或方法属于类级别,可直接通过类名调用,无需实例化。常用于工具类或共享数据。 ```java public class MathUtils { public static final double PI = 3.14159; // 常量 public static int add(int a, int b) { return a + b; } } // 调用:MathUtils.add(2, 3); ``` - **静态块(Java)** 用于初始化静态变量,在类加载时执行一次。 ```java static { System.loadLibrary("mylib"); } ``` - **静态类(C#)** 静态类不可实例化,仅包含静态成员。 ```csharp public static class Logger { public static void Log(string message) { ... } } ``` --- #### 3. **JavaScript 中的 `static`**(ES6+) - **类方法/属性** 静态方法通过类直接调用,不能访问实例成员。 ```javascript class ArrayUtils { static isEmpty(arr) { return arr.length === 0; } } // 调用:ArrayUtils.isEmpty([1,2]); ``` --- #### 4. **其他语言的 `static`** - **PHP**:在类方法中声明静态属性,或通过 `self::` 访问静态成员。 - **Python**:通过类变量实现类似功能,无显式 `static` 关键字,但可用装饰器 `@staticmethod` 定义静态方法。 --- ### 核心目的总结 1. **控制作用域**:限制变量/函数的可见范围(如 C 文件级静态变量)。 2. **管理生命周期**:延长局部变量的存储周期(如函数内静态变量)。 3. **共享性**:提供类级别的共享数据或方法(如 Java 静态变量)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值