成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一字千金:C語言中的 static:一個(gè)關(guān)鍵字,三種超能力 !

開發(fā)
今天咱們來聊一個(gè)看起來普普通通,用起來卻異常強(qiáng)大的 C 語言關(guān)鍵字——static。它就像是代碼中的"隱形斗篷",神不知鬼不覺地改變著你程序的行為。

嘿,各位編程小伙伴們!我是小康。

今天咱們來聊一個(gè)看起來普普通通,用起來卻異常強(qiáng)大的 C 語言關(guān)鍵字——static。它就像是代碼中的"隱形斗篷",神不知鬼不覺地改變著你程序的行為。

很多初學(xué)者對(duì)它一知半解,要么不敢用,要么用錯(cuò)了還不知道為啥。今天我就用大白話幫你徹底搞懂它!

一、static 是啥玩意兒?不就是個(gè)關(guān)鍵字嗎?

別小看這個(gè)小小的關(guān)鍵字,它可是 C 語言中的多面手!根據(jù)不同的使用場景,static 有著完全不同的功能:

  • 用在 局部變量 前面:讓變量擁有"記憶力"
  • 用在 全局變量/函數(shù) 前面:讓它們變得"害羞"(只在本文件可見)
  • 用在 類/結(jié)構(gòu)體成員 前面:讓所有對(duì)象共享一個(gè)變量

好家伙,一個(gè)詞能干三種活,難怪很多人搞不明白!但別擔(dān)心,我們一個(gè)一個(gè)來解釋,保證你能徹底搞懂!

二、場景一:給局部變量加上"記憶力"

平常我們定義的局部變量,函數(shù)調(diào)用結(jié)束后就"揮手告別"了,下次再調(diào)用函數(shù)時(shí),變量又會(huì)重新初始化。但加上 static 后,這個(gè)變量就有了"記憶力",能夠記住上次函數(shù)調(diào)用后的值!

看個(gè)例子就明白了:

#include <stdio.h>

// 沒有static的普通函數(shù)
void normalCounter() {
    int count = 0;  // 每次調(diào)用都會(huì)重置為0
    count++;
    printf("普通計(jì)數(shù)器:%d\n", count);
}

// 使用static的函數(shù)
void staticCounter() {
    staticint count = 0;  // 只在第一次調(diào)用時(shí)初始化為0
    count++;              // 以后每次調(diào)用都在上次的基礎(chǔ)上+1
    printf("static計(jì)數(shù)器:%d\n", count);
}

int main() {
    // 調(diào)用3次看看效果
    for (int i = 0; i < 3; i++) {
        normalCounter();
        staticCounter();
        printf("-------------------\n");
    }
    return0;
}

運(yùn)行結(jié)果:

普通計(jì)數(shù)器:1
static計(jì)數(shù)器:1
-------------------
普通計(jì)數(shù)器:1
static計(jì)數(shù)器:2
-------------------
普通計(jì)數(shù)器:1
static計(jì)數(shù)器:3
-------------------

看到差別了嗎?沒加 static 的count,每次都是從 0 開始,加 1 后變成 1;而加了 static 的count,第一次是1,第二次是 2,第三次是 3,它記住了自己上次的值!

這有啥用?想想以下場景:

  • 需要記錄函數(shù)被調(diào)用了多少次
  • 需要緩存計(jì)算結(jié)果,避免重復(fù)計(jì)算
  • 需要檢測是否是第一次調(diào)用函數(shù)

static 局部變量的特點(diǎn):

  • 值會(huì)保留:函數(shù)調(diào)用結(jié)束后,變量的值不會(huì)消失
  • 只初始化一次:static int x = 10; 這個(gè)初始化只會(huì)在程序第一次執(zhí)行到這句話時(shí)進(jìn)行
  • 內(nèi)存位置:放在靜態(tài)存儲(chǔ)區(qū),而不是棧上
  • 默認(rèn)值為0:如果不初始化,自動(dòng)設(shè)為 0(普通局部變量不初始化則是隨機(jī)值)

三、場景二:讓全局變量/函數(shù)變"害羞"(限制可見性)

在沒有 static 的情況下,一個(gè) C 文件(也叫翻譯單元)中定義的全局變量和函數(shù),默認(rèn)對(duì)其他文件也是可見的。但有時(shí)候,我們希望某些函數(shù)和變量是"內(nèi)部實(shí)現(xiàn)細(xì)節(jié)",不想讓其他文件看到和使用。

這時(shí)候,static 就派上用場了!它能讓全局變量和函數(shù)變得"害羞"起來,只在定義它的文件內(nèi)可見。

假設(shè)我們有兩個(gè)文件:

  • file1.c
#include <stdio.h>

// 普通全局變量:其他文件可以訪問
int globalCounter = 0;

// static全局變量:只有本文件能訪問
staticint privateCounter = 0;

// 普通函數(shù):其他文件可以調(diào)用
void increaseGlobal() {
    globalCounter++;
    printf("全局計(jì)數(shù)器:%d\n", globalCounter);
}

// static函數(shù):只有本文件能調(diào)用
static void increasePrivate() {
    privateCounter++;
    printf("私有計(jì)數(shù)器:%d\n", privateCounter);
}

// 公開函數(shù),內(nèi)部使用私有計(jì)數(shù)器
void accessPrivate() {
    increasePrivate();  // 可以調(diào)用static函數(shù)
    printf("通過接口訪問私有計(jì)數(shù)器\n");
}
  • file2.c
#include <stdio.h>

// 聲明外部全局變量
externint globalCounter;

// 無法訪問privateCounter,因?yàn)樗莝tatic的

// 聲明外部函數(shù)
void increaseGlobal();
void accessPrivate();

int main() {
    increaseGlobal();  // 可以調(diào)用
    // increasePrivate();  // 錯(cuò)誤!無法調(diào)用static函數(shù)
    accessPrivate();   // 可以通過公開接口間接使用
    
    printf("在main中訪問全局計(jì)數(shù)器:%d\n", globalCounter);
    // printf("在main中訪問私有計(jì)數(shù)器:%d\n", privateCounter);  // 錯(cuò)誤!無法訪問
    
    return0;
}

輸出結(jié)果:

全局計(jì)數(shù)器:1
私有計(jì)數(shù)器:1
通過接口訪問私有計(jì)數(shù)器
在main中訪問全局計(jì)數(shù)器:1

這個(gè)例子說明:

  • globalCounter和increaseGlobal()在兩個(gè)文件間共享
  • privateCounter和increasePrivate()只在 file1.c 中可見
  • 需要使用私有功能時(shí),必須通過公開的"接口函數(shù)"如accessPrivate()

static 全局變量/函數(shù)的特點(diǎn):

  • 限制作用域:只在定義的文件內(nèi)可見
  • 避免命名沖突:不同文件可以使用相同名稱的 static 變量/函數(shù)
  • 隱藏實(shí)現(xiàn)細(xì)節(jié):將內(nèi)部使用的輔助函數(shù)設(shè)為 static
  • 提高編譯效率:編譯器可以對(duì) static 函數(shù)進(jìn)行更多優(yōu)化

四、場景三:在結(jié)構(gòu)體/類中創(chuàng)建共享變量

C++中,可以在類中定義 static 成員變量,所有對(duì)象共享同一個(gè)變量。雖然 C 語言沒有類,但在一些 C++風(fēng)格的C 代碼中也會(huì)用到這個(gè)概念:

#include <stdio.h>

// 假設(shè)這是一個(gè)簡單的"類"
typedefstruct {
    int id;
    char* name;
    // 注意:在C中不能在結(jié)構(gòu)體內(nèi)直接定義static變量
} Person;

// 在C中,我們?cè)诮Y(jié)構(gòu)體外定義static變量
staticint Person_count = 0;

// "構(gòu)造函數(shù)"
Person createPerson(char* name) {
    Person p;
    p.id = ++Person_count;  // 每創(chuàng)建一個(gè)Person,計(jì)數(shù)器就+1
    p.name = name;
    return p;
}

// 獲取創(chuàng)建的Person總數(shù)
int getPersonCount() {
    return Person_count;
}

int main() {
    Person p1 = createPerson("張三");
    Person p2 = createPerson("李四");
    Person p3 = createPerson("王五");
    
    printf("已創(chuàng)建的Person對(duì)象數(shù)量:%d\n", getPersonCount());
    printf("各Person的ID:%d, %d, %d\n", p1.id, p2.id, p3.id);
    
    return0;
}

運(yùn)行結(jié)果:

已創(chuàng)建的Person對(duì)象數(shù)量:3
各Person的ID:1, 2, 3

在這個(gè)例子中,Person_count在所有Person對(duì)象之間共享,用來記錄創(chuàng)建了多少個(gè)對(duì)象,并為每個(gè)對(duì)象分配唯一ID。

五、深入理解 static:生命周期 vs 作用域

很多人搞混了 static 的兩個(gè)作用:改變 生命周期和改變 作用域。

生命周期:變量存在的時(shí)間

  • 普通局部變量:函數(shù)調(diào)用期間存在
  • static 局部變量:程序運(yùn)行期間一直存在

作用域:變量可見的范圍

  • 普通全局變量:所有文件可見
  • static 全局變量:僅定義它的文件可見

六、幾個(gè)常見的 static 使用場景

1. 單例模式的實(shí)現(xiàn)(非線程安全)

#include <stdio.h>
#include <stdlib.h>

typedefstruct {
    int data;
} Singleton;

Singleton* getInstance() {
    static Singleton* instance = NULL;
    
    if (instance == NULL) {
        // 第一次調(diào)用時(shí)創(chuàng)建對(duì)象
        instance = (Singleton*)malloc(sizeof(Singleton));
        instance->data = 42;
        printf("創(chuàng)建了單例對(duì)象\n");
    }
    
    return instance;
}

int main() {
    Singleton* s1 = getInstance();
    Singleton* s2 = getInstance();
    
    printf("s1的地址:%p, 數(shù)據(jù):%d\n", (void*)s1, s1->data);
    printf("s2的地址:%p, 數(shù)據(jù):%d\n", (void*)s2, s2->data);
    
    // 修改s1的數(shù)據(jù)
    s1->data = 100;
    
    // 檢查s2是否也改變了
    printf("修改后,s2的數(shù)據(jù):%d\n", s2->data);
    
    // 注意:在實(shí)際應(yīng)用中還需要處理內(nèi)存釋放問題
    
    return0;
}

運(yùn)行結(jié)果:

創(chuàng)建了單例對(duì)象
s1的地址:00C37F28, 數(shù)據(jù):42
s2的地址:00C37F28, 數(shù)據(jù):42
修改后,s2的數(shù)據(jù):100

這個(gè)例子實(shí)現(xiàn)了單例模式:無論調(diào)用多少次getInstance(),都只會(huì)創(chuàng)建一個(gè)Singleton對(duì)象。

不過要注意,這個(gè)實(shí)現(xiàn)在多線程環(huán)境下可能會(huì)出問題。想象兩個(gè)線程同時(shí)首次調(diào)用 getInstance(),它們都發(fā)現(xiàn)instance == NULL,然后都創(chuàng)建了對(duì)象!解決這個(gè)問題需要加鎖或使用原子操作,這就是所謂的"線程安全單例模式"。

2. 計(jì)算斐波那契數(shù)列(使用緩存)

#include <stdio.h>

// 使用static數(shù)組緩存結(jié)果,避免重復(fù)計(jì)算
unsigned long long fibonacci(int n) {
    staticunsignedlonglong cache[100] = {0};  // 緩存結(jié)果
    staticint initialized = 0;
    
    // 初始化前兩個(gè)數(shù)
    if (!initialized) {
        cache[0] = 0;
        cache[1] = 1;
        initialized = 1;
    }
    
    // 如果結(jié)果已經(jīng)計(jì)算過,直接返回
    if (cache[n] != 0 || n <= 1) {
        return cache[n];
    }
    
    // 計(jì)算并緩存結(jié)果
    cache[n] = fibonacci(n-1) + fibonacci(n-2);
    return cache[n];
}

int main() {
    printf("斐波那契數(shù)列的第40個(gè)數(shù):%llu\n", fibonacci(39));
    // 再次計(jì)算,會(huì)直接使用緩存
    printf("再次計(jì)算,斐波那契數(shù)列的第40個(gè)數(shù):%llu\n", fibonacci(39));
    
    return0;
}

這個(gè)例子使用 static 數(shù)組緩存了已計(jì)算的結(jié)果,大大提高了效率。

七、static 的常見坑和注意事項(xiàng)

  • 不要在頭文件中定義 static 全局變量/函數(shù) :  如果在頭文件中定義static變量/函數(shù),每個(gè)包含該頭文件的源文件都會(huì)創(chuàng)建自己的副本,可能導(dǎo)致意想不到的結(jié)果。
  • 初始化順序:  static 變量的初始化發(fā)生在程序啟動(dòng)時(shí),但是不同文件中的static變量初始化順序是不確定的。
  • 多線程安全問題:  多線程同時(shí)訪問 static 變量可能導(dǎo)致競態(tài)條件,需要使用互斥鎖保護(hù)。

八、總結(jié):static 的三個(gè)"超能力"

  • 記憶力:static 局部變量記住調(diào)用間的狀態(tài)
  • 隱身術(shù):static 全局變量/函數(shù)隱藏實(shí)現(xiàn)細(xì)節(jié)
  • 共享精神:static 在"類"中用于共享數(shù)據(jù)

掌握了這三點(diǎn),你就能在編程中靈活運(yùn)用 static,讓你的程序更高效、更安全、更優(yōu)雅!

責(zé)任編輯:趙寧寧 來源: 跟著小康學(xué)編程
相關(guān)推薦

2015-11-10 16:10:22

C語言StaticConst

2024-06-04 17:02:38

newC#編程語言

2015-03-13 11:23:21

編程編程超能力編程能力

2019-02-28 22:10:30

AI人工智能預(yù)測

2024-05-29 14:09:00

C#編程this

2009-06-29 12:58:47

This關(guān)鍵字java

2011-07-14 23:14:42

C++static

2022-02-17 08:31:38

C語言staic關(guān)鍵字

2021-02-01 13:10:07

Staticc語言UNIX系統(tǒng)

2024-12-31 00:05:24

new?關(guān)鍵字C#

2010-02-02 14:27:54

C++ static關(guān)

2022-01-10 18:11:42

C語言應(yīng)用技巧

2024-03-15 08:18:25

volatileAtomic關(guān)鍵字

2011-02-22 17:48:34

Konqueror

2023-11-12 23:01:44

PaddleOCR深度學(xué)習(xí)

2011-04-21 16:57:56

staticextern

2024-04-08 11:35:34

C++static關(guān)鍵字

2021-08-03 21:24:13

ARVR

2020-12-09 05:19:35

static關(guān)鍵字Java

2019-03-28 09:26:26

數(shù)據(jù)科學(xué)模型機(jī)器學(xué)習(xí)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 999久久久免费精品国产 | 中文字幕99 | 欧美亚洲另类丝袜综合网动图 | 欧美精品三区 | 国产成人91视频 | 黄网站涩免费蜜桃网站 | 成人精品在线观看 | 韩国精品一区二区三区 | 天天躁日日躁性色aⅴ电影 免费在线观看成年人视频 国产欧美精品 | 蜜桃av人人夜夜澡人人爽 | 中文字幕 在线观看 | 中文字幕 国产精品 | 欧美一二三四成人免费视频 | 国产精品成人在线 | 一区二区三区四区国产 | 精品国产黄色片 | 99精品国产成人一区二区 | 91中文在线观看 | 日本色综合 | 国产精品揄拍一区二区 | 久久久久久免费精品一区二区三区 | 五月综合久久 | 久久91精品国产一区二区 | 欧美精品一区二区三区四区五区 | 精品视频久久久久久 | 成人免费精品视频 | 一级片在线观看视频 | 一区二区三区在线播放 | 久久久久久a| 国产一级一级国产 | 欧美日韩国产精品一区 | 中国一级特黄真人毛片免费观看 | 国产91网址 | 春色av| 五月天婷婷激情 | 午夜精品久久久久久久久久久久久 | www.黄色在线观看 | 久草电影网 | h视频在线免费 | 成人欧美一区二区三区黑人孕妇 | 午夜天堂精品久久久久 |