動態

詳情 返回 返回

零長數組初識 - 動態 詳情

前言

本來是解決frr在交叉編譯時,編譯mips架構不可用的問題,後來排查到是因為一個數組的問題,然後無意中看到一個詞---零長數組。嘿,還挺新鮮,以前真沒用過。研究了一下,感覺還挺實用。

例子

廢話不多少,先上例子,看咋用:

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

#define MAX_LENGTH 10

// 0長度數組
struct zero_buffer {
    int len;
    char data[0];
};

// 定長數組
struct max_buffer {
    int len;
    char data[MAX_LENGTH];
};

// 指針
struct point_buffer {
    int len;
    char *data;
};

// 函數,演示三種不同的數據結構
void demonstrateDataStructures() {
    // 共用的數據
    int data_length = 15;
    char data[] = "Hello, GPT!";
    
    // 使用零長數組
    struct zero_buffer *zbuffer = malloc(sizeof(struct zero_buffer) + sizeof(char) * data_length);
    
    if (zbuffer) {
        zbuffer->len = data_length;
        strcpy(zbuffer->data, data);

        printf("Zero-length Array: Length=%d, Data=%s\n", zbuffer->len, zbuffer->data);

        // 釋放內存
        free(zbuffer);
    }

    // 使用定長數組
    struct max_buffer mbuffer;
    mbuffer.len = data_length;
    strcpy(mbuffer.data, data);

    printf("Fixed-length Array: Length=%d, Data=%s\n", mbuffer.len, mbuffer.data);

    // 使用指針
    struct point_buffer pbuffer;
    pbuffer.len = data_length;
    pbuffer.data = malloc(sizeof(char) * data_length);

    if (pbuffer.data) {
        strcpy(pbuffer.data, data);

        printf("Pointer Array: Length=%d, Data=%s\n", pbuffer.len, pbuffer.data);

        // 釋放內存
        free(pbuffer.data);
    }
}

int main(void) {
    demonstrateDataStructures();

    return 0;
}

打印:

Zero-length Array: Length=15, Data=Hello, GPT!
Fixed-length Array: Length=15, Data=Hello, GPT!
Pointer Array: Length=15, Data=Hello, GPT!

零長數組

零長數組是GCC(GNU Compiler Collection)的一個特定擴展功能,不是標準C語言的一部分。它是一種GNU C擴展,也稱為C語言的柔性數組(Flexible Array Member)。

這個擴展功能允許在結構體的末尾定義一個長度為零的數組,以實現動態內存分配和數據存儲。它在某些情況下非常有用,特別是在需要構建變長數據結構時,如動態字符串或變長記錄。

需要注意的是,零長數組的可移植性有限,因為它不是C標準的一部分,因此在使用零長數組時,代碼可能會依賴於特定的編譯器擴展。如果要確保代碼在不同編譯器上都能正常工作,建議謹慎使用零長數組,或者考慮使用其他方式來實現相同的功能,比如指針數組或動態內存分配。

詳細解釋:

  • 定義:一個結構體內的數組,其長度為零。它通常用在結構體的末尾,充當一個佔位符,用於在運行時動態分配內存以存儲可變長度的數據
  • 不佔用額外的內存:零長數組本身不佔用額外的內存空間,即它不增加結構體的大小。相當於一個指向變長數據的起始位置的引用,它的長度在運行時根據需要動態分配。
  • 動態內存分配: 為了使用零長數組來存儲數據,你需要使用動態內存分配函數,如malloc,來分配足夠的內存以容納零長數組中的數據。這個分配的內存塊的大小由結構體的大小和實際數據長度的總和決定。
  • 數據存儲: 一旦內存分配完成,你可以將數據存儲在零長數組中,就像使用普通數組一樣。你可以使用各種C字符串和數據操作函數來處理零長數組中的數據。
  • 動態長度: 零長數組允許你在運行時更改數據的長度,因為它不會限制你的數據存儲大小。這對於實現動態數據結構非常有用,例如可變大小的字符串。
  • 內存管理:與使用malloc分配的內存一樣,你需要小心管理零長數組的內存。確保在不再需要數據時釋放內存,以防止內存泄漏。

為什麼會有零長數組

定長數組

  • 固定大小: 定長數組的大小是固定的,這意味着如果你需要存儲不同長度的數據,你必須為最大可能的長度分配內存,可能會浪費內存。
  • 內存浪費: 如果你的數據長度遠小於數組的最大大小,會導致內存浪費。例如,如果數組大小是100,但你只需要存儲10個元素,就會浪費大量內存。

指針

  • 避免內存浪費:如果將定長數組char data[MAX_LENGTH];換成 char *data;,避免了內存浪費,相對來説只浪費了一個指針域的空間。
  • 內存泄漏:過程相對繁瑣一些:

    • 首先,要為結構體申請一塊內存;
    • 其次哈要為char *data申請空間;
    • 用完之後上面的空間都要釋放,如果不謹慎,很大可能會造成內存泄漏。

那零長到底佔用空間麼

以下僅為個人理解。
零長數組本身並不存儲數據,但它可以作為一個佔位符,用於動態分配和管理內存,以存儲數據。
例如上面的例子,首先使用malloc分配了足夠的內存來容納零長數組的數據,並使用strcpy將數據複製到零長數組中。
零長數組的作用在於允許動態地分配不同長度的數據,而不佔用額外的內存空間。
零長數組的關鍵是它不會佔用額外的內存空間,但一旦你將數據複製到零長數組中,它會佔用zbuffer指針所指向的那塊內存空間。零長數組本身不會增加這塊內存的大小,但它可以靈活地存儲不同長度的數據。

一旦使用strcpy將數據複製到zbuffer中,zbuffer所指向的內存塊中的一部分就被佔用了。這個佔用的內存大小由你分配的內存塊的大小決定。當你使用malloc分配內存時,分配的內存大小足夠容納sizeof(struct zero_buffer)和數據長度的總和。

 

永遠不要停止追求卓越,因為你的夢想值得每一分努力。
歡迎關注個人博客溝通交流

Add a new 評論

Some HTML is okay.