1. 程式人生 > 其它 >C語言-0位元組長度陣列的使用

C語言-0位元組長度陣列的使用

技術標籤:C/C++c語言嵌入式指標陣列

奇怪的知識又增加了-0位元組長度陣列的使用

引言

最近看了一些網路程式設計的書,學到了一些C語言的“奇巧淫技”,遂開此欄目,進行記載。
問題引出:
試求以下兩個結構體的長度,並簡述如何使用這種0位元組長度的陣列

typedef struct zero_byte_buffer1 {
    uint8_t status;
    int len;
    char data[0]; 
} zero_byte_buffer1_t;

typedef struct zero_byte_buffer2 {
    uint8_t status;
    uint8_t len;
    uint32_t data[0]; 
} zero_byte_buffer2_t;

測試程式與結果分析

GNU C中提供了這種0長度陣列的支援,只要將0長度陣列放在結構體的末尾就可以在支援GNU C的編譯器中編譯通過上述結構體,並方便的使用它們。
當然學習這種“奇巧淫技”的最好方法就是測試它、對比它,知其然知其所以然,就能化為己用,上程式碼:

/* Zero_byte_array
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"

#define MAX_LENGTH 1024
#define CURRENT_LENGTH 3

typedef struct zero_byte_buffer1 {
    uint8_t status;
    int len;
    char data[0]; 
} zero_byte_buffer1_t;

typedef struct zero_byte_buffer2 {
    uint8_t status;
    uint8_t len;
    uint32_t data[0]; 
} zero_byte_buffer2_t;

typedef struct fixed_length_buffer {
    int     len;
    char    data[MAX_LENGTH];
} fixed_length_buffer_t;

typedef struct variable_length_buffer {
    int len;
    char *data;
} variable_length_buffer_t;

void app_main(void)
{
    printf("TEST Begin\r\n");

    zero_byte_buffer1_t* zero_byte_buffer1;
    fixed_length_buffer_t* fixed_length_buffer;
    variable_length_buffer_t* variable_length_buffer;

    printf("zero_byte_buffer1 length is %d\r\n", sizeof(zero_byte_buffer1_t));
    printf("zero_byte_buffer2 length is %d\r\n", sizeof(zero_byte_buffer2_t));
    printf("fixed_length_buffer length is %d\r\n", sizeof(fixed_length_buffer_t));
    printf("variable_length_buffer length is %d\r\n", sizeof(variable_length_buffer_t));

    /*use zero_byte_buffer*/
    /*1. malloc*/
     if ((zero_byte_buffer1 = (zero_byte_buffer1_t *)malloc(sizeof(zero_byte_buffer1_t) + sizeof(char) * CURRENT_LENGTH)) != NULL) {
        zero_byte_buffer1->len = CURRENT_LENGTH;
        memcpy(zero_byte_buffer1->data, "OK", CURRENT_LENGTH);
        printf("%d, %s\n", zero_byte_buffer1->len, zero_byte_buffer1->data);
    }
    /*2. free*/
    free(zero_byte_buffer1);
    zero_byte_buffer1 = NULL;

    /*use fixed_length_buffer*/
    /*1. malloc*/
    if ((fixed_length_buffer = (fixed_length_buffer_t *)malloc(sizeof(fixed_length_buffer_t))) != NULL) {
        fixed_length_buffer->len = CURRENT_LENGTH;
        memcpy(fixed_length_buffer->data, "OK", CURRENT_LENGTH);

        printf("%d, %s\n", fixed_length_buffer->len, fixed_length_buffer->data);
    }
    /*2. free*/
    free(fixed_length_buffer);
    fixed_length_buffer = NULL;

    /*use fixed_length_buffer*/
    /*1. malloc*/
    if ((variable_length_buffer = (variable_length_buffer_t *)malloc(sizeof(variable_length_buffer_t))) != NULL)
    {
        variable_length_buffer->len = CURRENT_LENGTH;
        if ((variable_length_buffer->data = (char *)malloc(sizeof(char) * CURRENT_LENGTH)) != NULL)
        {
            memcpy(variable_length_buffer->data, "OK", CURRENT_LENGTH);
            printf("%d, %s\n", variable_length_buffer->len, variable_length_buffer->data);
        }
    }
    /*2. free*/
    free(variable_length_buffer->data);
    free(variable_length_buffer);
    variable_length_buffer = NULL;
}

編譯執行結果:

TEST Begin
zero_byte_buffer1 length is 8
zero_byte_buffer2 length is 4
fixed_length_buffer length is 1028
variable_length_buffer length is 8
3, OK
3, OK
3, OK

通過測試結果可以發現:
1.比較zero_byte_buffer1 length is 8 和zero_byte_buffer2 length is 4兩條測試結果可知
0位元組長度的陣列,自己本身並不佔用結構體的空間,但是會影響結構體的位元組對齊。

2.什麼時間使用0位元組長度的陣列呢?

比較使用zero_byte_buffer(使用0位元組長度的陣列的buffer型別)、 fixed_length_buffe(使用定長陣列的buffer)、variable_length_buffer(使用變長陣列、或說指標的buffer)的三種方法,可見,通過使用0位元組長度的陣列,zero_byte_buffer實現了可變長的buffer型別。

這種可變長的buffer型別的好處是:
1)相比使用定長陣列的buffer ,即fixed_length_buffe,其data的長度是可變的,可根據當前實際的data的長度進行靈活的申請需要的空間。
2)相比於使用變長陣列的buffer,即variable_length_buffer,其節省了一個malloc 、free時的操作步驟,即variable_length_buffer需要兩次malloc、兩次free,但zero_byte_buffer只需一次malloc和一次free。

(謝謝點贊或收藏,比心)