自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

那些年我們踩過的坑:C 語言柔性數(shù)組其實(shí)超簡單!

開發(fā)
今天咱們來聊一個(gè)看起來高大上,其實(shí)超級(jí)實(shí)用的 C 語言知識(shí)點(diǎn)——柔性數(shù)組。

大家好啊,我是小康。

今天咱們來聊一個(gè)看起來高大上,其實(shí)超級(jí)實(shí)用的 C 語言知識(shí)點(diǎn)——柔性數(shù)組。

別被這個(gè)名字唬住,啥叫"柔性"?簡單說就是大小可變、長度不固定的數(shù)組。學(xué)會(huì)這招,分分鐘提升你的程序設(shè)計(jì)水平!

一、啥是柔性數(shù)組?先別慌!

你肯定用過普通數(shù)組吧?比如:int nums[10]。這種數(shù)組大小一旦定了就是10個(gè)元素,多一個(gè)少一個(gè)都不行,死板得很!

而柔性數(shù)組是啥呢?它是 C99 標(biāo)準(zhǔn)引入的一個(gè)神奇特性,允許我們?cè)诮Y(jié)構(gòu)體的最后聲明一個(gè)大小未知的數(shù)組。是不是聽著很玄乎?別著急,看完你就懂了!

二、柔性數(shù)組長啥樣?

struct FlexArray {
    int length;     // 記錄數(shù)組長度
    double scores[]; // 這就是柔性數(shù)組!注意這里沒寫大小
};

看到了嗎?這個(gè)scores數(shù)組后面的中括號(hào)是空的!這就是柔性數(shù)組的寫法。它必須是結(jié)構(gòu)體的最后一個(gè)成員,前面必須至少有一個(gè)其他成員(通常用來記錄數(shù)組的實(shí)際長度)。

三、為啥要用柔性數(shù)組?有啥好處?

想象一下這個(gè)場(chǎng)景:你要管理不同學(xué)生的成績,有的學(xué)生選了 3 門課,有的選了 8 門課。用普通數(shù)組咋辦?

方法一:定一個(gè)夠大的數(shù)組,比如:

struct Student {
    int id;
    int courseCount;
    double scores[30]; // 寫死30個(gè),夠大就行
};

// 使用方式
struct Student xiaoming;
xiaoming.id = 1001;
xiaoming.courseCount = 5;
xiaoming.scores[0] = 85.5;
// ...

問題來了,太浪費(fèi)空間了!小明只選了 5 門課,但我們卻給他預(yù)留了 30 門課的空間。而且,萬一有學(xué)霸選了超過 30 門課呢?改代碼重新編譯?這也太麻煩了!

方法二:用指針和動(dòng)態(tài)內(nèi)存,比如:

struct Student {
    int id;
    int courseCount;
    double *scores; // 指針,指向另一塊內(nèi)存
};

// 使用方式
struct Student *xiaoming = (struct Student*)malloc(sizeof(struct Student));
xiaoming->id = 1001;
xiaoming->courseCount = 5;

// 再分配一次內(nèi)存給成績數(shù)組
xiaoming->scores = (double*)malloc(5 * sizeof(double));
xiaoming->scores[0] = 85.5;
// ...

// 釋放內(nèi)存時(shí)要記得釋放兩次!
free(xiaoming->scores); // 先釋放數(shù)組
free(xiaoming);         // 再釋放結(jié)構(gòu)體

這種方式雖然靈活,但每次都要分兩次申請(qǐng)內(nèi)存:一次給結(jié)構(gòu)體,一次給 scores 指向的數(shù)組。 內(nèi)存不連續(xù),訪問效率低,而且容易忘記釋放內(nèi)存(特別是那個(gè) scores 指針指向的內(nèi)存,很多人只釋放了結(jié)構(gòu)體,忘了釋放數(shù)組,造成內(nèi)存泄漏)。

這時(shí)候,柔性數(shù)組就顯得特別聰明了!

四、柔性數(shù)組是怎么用的?實(shí)戰(zhàn)來了!

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

// 定義一個(gè)帶柔性數(shù)組的結(jié)構(gòu)體
struct Student {
    int id;          // 學(xué)號(hào)
    int courseCount; // 課程數(shù)量
    double scores[]; // 柔性數(shù)組,存儲(chǔ)成績
};

int main() {
    int courses = 5; // 小明選了5門課
    
    // 計(jì)算需要的總內(nèi)存:結(jié)構(gòu)體固定部分 + 柔性數(shù)組部分
    struct Student *xiaoming = (struct Student*)malloc(sizeof(struct Student) + courses * sizeof(double));
    
    // 初始化小明的信息
    xiaoming->id = 1001;
    xiaoming->courseCount = courses;
    
    // 設(shè)置小明的5門課成績
    xiaoming->scores[0] = 85.5; // 數(shù)學(xué)
    xiaoming->scores[1] = 92.0; // 英語
    xiaoming->scores[2] = 78.5; // 物理
    xiaoming->scores[3] = 96.0; // 化學(xué)
    xiaoming->scores[4] = 88.5; // 生物
    
    // 計(jì)算平均分
    double sum = 0;
    for (int i = 0; i < xiaoming->courseCount; i++) {
        sum += xiaoming->scores[i];
    }
    
    printf("學(xué)號(hào)%d的小明平均分是:%.2f\n", xiaoming->id, sum / xiaoming->courseCount);
    
    // 釋放內(nèi)存,只需要free一次!
    free(xiaoming);
    
    return0;
}

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

學(xué)號(hào)1001的小明平均分是:88.10

五、柔性數(shù)組的內(nèi)存布局,一圖看懂!

假設(shè)我們有這樣的結(jié)構(gòu)體:

struct FlexArray {
    int length;
    double scores[];
};

內(nèi)存中的樣子大概是:

+-------------+-------------+-------------+-------------+
| length (4B) | scores[0]   | scores[1]   | scores[2]   | ...
+-------------+-------------+-------------+-------------+
               ↑
        柔性數(shù)組的起始位置

所有數(shù)據(jù)都在一塊連續(xù)的內(nèi)存中,訪問超快,而且只需要分配和釋放一次內(nèi)存!

六、柔性數(shù)組的注意事項(xiàng)(踩坑警告??)

必須放在結(jié)構(gòu)體最后:柔性數(shù)組必須是結(jié)構(gòu)體的最后一個(gè)成員。

至少有一個(gè)其他成員:結(jié)構(gòu)體中必須有至少一個(gè)其他成員(通常用來記錄柔性數(shù)組的長度)。

不占結(jié)構(gòu)體大?。喝嵝詳?shù)組不計(jì)入結(jié)構(gòu)體的 sizeof 大小。

struct Test {
    int n;
    int arr[];
};

printf("結(jié)構(gòu)體大小:%zu\n", sizeof(struct Test)); // 輸出:結(jié)構(gòu)體大?。?

不能直接定義變量:不能直接定義結(jié)構(gòu)體變量,必須用指針和動(dòng)態(tài)內(nèi)存。

// 錯(cuò)誤寫法
struct Test t;  // 不行!柔性數(shù)組沒地方存
               // 注意:雖然在 VS2022 等現(xiàn)代編譯器中可能編譯通過
               // 但這是不規(guī)范的,柔性數(shù)組沒有實(shí)際存儲(chǔ)空間,使用會(huì)導(dǎo)致內(nèi)存越界!

// 正確寫法
struct Test *pt = (struct Test*)malloc(sizeof(struct Test) + 10 * sizeof(int));

七、柔性數(shù)組vs指針成員,差別在哪?

有人可能會(huì)問:用結(jié)構(gòu)體里的指針成員不也能實(shí)現(xiàn)類似功能嗎?

struct WithPointer {
    int length;
    int *data;  // 指針成員
};

struct WithFlexible {
    int length;
    int data[]; // 柔性數(shù)組
};

區(qū)別大了去了:

  • 內(nèi)存布局:柔性數(shù)組的數(shù)據(jù)緊跟在結(jié)構(gòu)體后面,是一塊連續(xù)內(nèi)存;指針方式數(shù)據(jù)在另一個(gè)地方,是兩塊不連續(xù)的內(nèi)存。
  • 內(nèi)存操作次數(shù):柔性數(shù)組只需要分配和釋放一次內(nèi)存;指針方式需要分配和釋放兩次。
  • 訪問效率:柔性數(shù)組訪問更快,內(nèi)存連續(xù),對(duì) CPU 緩存更友好。
  • 代碼簡潔度:柔性數(shù)組代碼更簡潔,不容易出現(xiàn)忘記釋放內(nèi)存的問題。

八、實(shí)戰(zhàn)案例:實(shí)現(xiàn)一個(gè)簡單的動(dòng)態(tài)字符串

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

typedefstruct {
    size_t length;  // 字符串長度
    char data[];    // 柔性數(shù)組
} MyString;

// 創(chuàng)建字符串
MyString* createString(const char* text) {
    size_t len = strlen(text);
    
    // 分配內(nèi)存:結(jié)構(gòu)體大小 + 字符串長度 + 1(給'\0'留位置)
    MyString* str = (MyString*)malloc(sizeof(MyString) + len + 1);
    
    str->length = len;
    strcpy(str->data, text);  // 復(fù)制字符串內(nèi)容
    
    return str;
}

// 打印字符串
void printString(const MyString* str) {
    printf("長度: %zu, 內(nèi)容: %s\n", str->length, str->data);
}

int main() {
    // 創(chuàng)建一個(gè)字符串
    MyString* hello = createString("Hello, 柔性數(shù)組!");
    
    // 打印字符串信息
    printString(hello);
    
    // 內(nèi)存釋放,只需要一次free
    free(hello);
    
    return0;
}

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

長度: 16, 內(nèi)容: Hello, 柔性數(shù)組!

總結(jié):柔性數(shù)組到底香在哪?

  • 內(nèi)存連續(xù):數(shù)據(jù)緊湊,訪問效率高
  • 一次分配:避免多次 malloc/free,減少內(nèi)存碎片
  • 一次釋放:不容易造成內(nèi)存泄漏
  • 靈活方便:可以根據(jù)需要分配剛好夠用的內(nèi)存

是不是感覺 C 語言突然變得更強(qiáng)大了?柔性數(shù)組這個(gè)小技巧,在很多底層庫和系統(tǒng)編程中都有廣泛應(yīng)用,比如 Linux 內(nèi)核中就大量使用了這個(gè)技術(shù)。

好了,今天的 C 語言小課堂到此結(jié)束!下次我們?cè)倭钠渌腥さ木幊碳记伞?/p>

掌握了柔性數(shù)組這個(gè)小技巧,是不是感覺自己的 C 語言技能又升級(jí)了?

寫在最后:技術(shù)成長沒有"固定數(shù)組"

就像柔性數(shù)組一樣,我們的學(xué)習(xí)之路也不該限定死板的大小。從 C 語言基礎(chǔ)到高級(jí)技巧,從編程小白到技術(shù)大牛,每個(gè)階段都需要不同"長度"的知識(shí)儲(chǔ)備。

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

2024-04-01 08:05:27

Go開發(fā)Java

2023-12-21 11:46:48

C語言柔性數(shù)組開發(fā)

2017-07-17 15:46:20

Oracle并行機(jī)制

2025-04-03 12:30:00

C 語言隱式類型轉(zhuǎn)換代碼

2020-11-18 10:16:23

人工智能機(jī)器學(xué)習(xí)技術(shù)

2018-01-10 13:40:03

數(shù)據(jù)庫MySQL表設(shè)計(jì)

2019-02-19 09:46:58

美圖容器化Kubernetes

2020-05-18 08:58:33

Python開發(fā)工具

2019-04-18 11:43:40

軟件卸載PC端

2024-05-06 00:00:00

緩存高并發(fā)數(shù)據(jù)

2015-03-24 16:29:55

默認(rèn)線程池java

2021-12-28 08:17:41

循環(huán) forgo

2025-04-29 10:17:42

2022-07-06 11:47:27

JAVAfor循環(huán)

2020-03-18 14:28:43

偽概念手機(jī)真相

2018-09-11 09:14:52

面試公司缺點(diǎn)

2023-03-13 13:36:00

Go擴(kuò)容切片

2023-12-14 17:34:22

Kubernetes集群K8s

2021-10-28 19:10:02

Go語言編碼

2018-07-30 16:18:51

容災(zāi)備份
點(diǎn)贊
收藏

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