c语言和c++中的静态关键字

static的核心作用可以归结为两个维度:存储期(生命周期) 和链接属性(可见范围)。

C++ 完全继承了 C 中 static 的所有用法,但在此基础上,针对**类(Class)**增加了两个全新的上下文。这是两者最本质的区别。

第一板块:C 和 C++ 共有的用法(底层内存逻辑)

在这一层,static 操作的是内存布局 和编译链接,与你之前学习的进程地址空间(代码段、数据段)紧密相关。

1. 修饰局部变量(改变存储期)

普通局部变量:存储在栈区,函数结束即销毁。

静态局部变量 :存储在静态存储区 (属于进程地址空间中的 .data 或 .bss 段),生命周期贯穿整个程序运行期 ,但作用域仍仅限于该函数内部。

核心特性:只在第一次执行到定义时初始化,之后调用保持上次的值。

cpp 复制代码
#include <stdio.h>

void counter() {
    static int count = 0; // 只初始化一次,存储在静态区
    count++;
    printf("调用次数: %d\n", count);
}

int main() {
    counter(); // 输出 1
    counter(); // 输出 2 (保留了上一次的值)
    return 0;
}
2. 修饰全局变量或函数(改变链接属性)

在 C/C++ 项目中,默认情况下全局变量和函数具有外部链接(External Linkage) ,即可以被其他 .c / .cpp 文件通过 extern 访问。

加上 static 后,将其改为内部链接(Internal Linkage) ,作用域被限制在当前源文件(编译单元)内,别的文件无法看到它。

这不仅是为了安全(封装),也能有效防止多文件编译时的重名冲突。

cpp 复制代码
// file: math_utils.c

// 全局静态变量:只能在本文件中使用,其他文件看不见
static int s_internal_counter = 100; 

// 静态函数:只能在本文件中调用,不会暴露给外部接口
static void helper_function() {
    printf("内部辅助函数\n");
}

// 普通函数:可以被外部文件调用
void public_function() {
    helper_function(); // 内部调用是允许的
}

第二板块:C++ 独有(类的静态成员)------ 最大的区别

这是 C 语言完全没有的领域。static 在这里不再关注"文件",而是关注"类(Class)"。

3. 静态成员变量(属于类,不属于对象)

内存归属 :无论创建多少个类对象(实例),静态成员变量只有一份内存副本 ,存放在全局静态区。它不属于某个具体的 this 对象。

初始化 :必须在类外 单独定义和初始化(除非使用 C++17 的 inline 修饰),因为它是"类级别"的资源,不能在构造函数中初始化。

cpp 复制代码
#include <iostream>
using namespace std;

class Student {
public:
    static int total_count; // 声明:统计一共创建了多少个学生

    Student() {
        total_count++; // 每构造一个对象,总数+1
    }
};

// 定义并初始化静态成员变量(必须在类外进行)
int Student::total_count = 0; 

int main() {
    cout << Student::total_count << endl; // 输出 0(通过类名直接访问)
    Student s1, s2;
    cout << Student::total_count << endl; // 输出 2
    cout << s1.total_count << endl;       // 输出 2(虽然可以通过对象访问,但本质是同一个)
    return 0;
}
4. 静态成员函数(属于类,无 this 指针)

没有 this 指针 :因此它不能访问类的普通成员变量(非静态)和普通成员函数,因为它不知道要操作哪个对象。

可访问范围 :只能访问静态成员变量 和其他静态成员函数。

调用方式 :可以直接通过 类名::函数名() 调用,不需要创建对象。

cpp 复制代码
class Tool {
private:
    static int version;
    int id; // 普通成员变量
public:
    static void showVersion() {
        cout << "Version: " << version << endl; // 正确,访问静态变量
        // cout << id << endl; // 报错!无法访问非静态成员,因为没有 this
    }
};

int Tool::version = 3;

int main() {
    Tool::showVersion(); // 直接通过类名调用,无需实例化
    return 0;
}
相关推荐
谢亮_vipxieliang13 分钟前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
longlongzihan20 分钟前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
时间的拾荒人26 分钟前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
郑州光合科技余经理35 分钟前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_9620715736 分钟前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-前后端分离开发模式与工程拆分
java·开发语言
Dovis(誓平步青云)2 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
sunshine22 girl2 小时前
Java学习六 Java常见API-2--String-3-字符串的截取替换和其他方法
java·开发语言·学习
LOVE️YOU2 小时前
Python 函数名、函数对象与“把函数作为参数传递”
开发语言·python
sunshine22 girl3 小时前
Java学习六 Java常见API-1-Radom随机数
java·开发语言·学习