精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

嵌入式中零長度數組基本操作方法

嵌入式開發星球 ? 來源:嵌入式開發愛好者 ? 作者:嵌入式開發愛好者 ? 2024-05-11 08:49 ? 次閱讀

C語言零長度數組,聽起來可能有點奇怪,因為它沒有分配內存空間,無法存儲數據。但實際上,零長度數組在Linux內核中隨處可見。

wKgaomY_FmCASuqKAACr-GPuQ2c182.png

零長度數組的定義

首先,我們要明白什么是零長度數組。簡單來說,零長度數組就是一個長度為0的數組,也就是說不包含任何元素的數組。零長度數組在C99標準中引入,并在C11中得到進一步的支持。其定義很簡單,就是一個大小為0的數組。例如:

int a[0];

在Linux內核中,零長度數組通常不會直接這樣使用,而是作為結構體中最后一個元素,配合動態內存分配來使用。

零長度數組在Linux內核中的應用案例

在Linux內核中,經常可以看到零長度數組被用作結構體末尾的占位符,以表示結構體的可變長度部分。例如,一個表示網絡套接字的struct sockaddr結構體可能如下所示:

struct sockaddr { sa_family_t sa_family; // 地址家族,如AF_INET, AF_UNIX等 char sa_data[14]; // 對于IPv4,這里實際上只有12字節被使用 };

在這個例子中,sa_data字段實際上是一個填充字段,用于容納不同地址家族的地址數據。由于地址家族可能不同,所需的數據長度也可能不同,因此這里使用了一個足夠大的固定長度數組。然而,如果使用零長度數組,代碼會更加清晰:

struct sockaddr { sa_family_t sa_family; // 地址家族 char sa_data[0]; // 可變長度部分,實際使用時會動態分配 };

在實際應用中,內核代碼會結合動態內存分配來設置需要的的sa_data長度,并填充相關的數據。零長度數組可以與kmalloc、vmalloc等內存分配函數結合使用,來實現這種動態分配,所以有人也把零長度數組稱為柔性數組。

如何具體實現結構體動態內存分配?

在Linux內核或其他C語言編寫的底層系統中,零長度數組經常被用作靈活的數據結構的一部分,特別是在需要動態增長或縮小的數組中。以下是一個簡單的示例,展示了如何在內核編程中使用零長度數組來實現一個可變長度的整數數組:

#include // 包含printk等內核函數 #include // 包含kmalloc和kfree等內存管理函數 // 定義一個結構體,用于表示可變長度的整數數組 struct variable_int_array { size_t length; // 數組當前長度 int data[0]; // 零長度數組,實際數據存儲在這里 }; // 創建一個新的可變長度整數數組 struct variable_int_array *create_int_array(size_t initial_length) { // 分配內存,包括結構體本身和初始長度的整數數組 struct variable_int_array *array = kmalloc( sizeof(struct variable_int_array) + initial_length * sizeof(int), GFP_KERNEL ); if (!array) { // 內存分配失敗 return NULL; } // 初始化數組長度 array->length = initial_length; // 返回新創建的數組 return array; } // 銷毀一個可變長度整數數組 void destroy_int_array(struct variable_int_array *array) { if (!array) { // 空指針檢查 return; } // 釋放內存 kfree(array); } // 向數組中添加一個新的整數 void add_int_to_array(struct variable_int_array **array_ptr, int value) { struct variable_int_array *array = *array_ptr; size_t new_length = array->length + 1; // 分配新的內存塊,包含擴展后的數組 array = kmalloc( sizeof(struct variable_int_array) + new_length * sizeof(int), GFP_KERNEL ); if (!array) { // 內存分配失敗 printk(KERN_ERR "Failed to extend the integer array.n"); return; } // 復制舊數組的值到新數組 memcpy(array->data, (*array_ptr)->data, array->length * sizeof(int)); // 添加新值 array->data[new_length - 1] = value; // 更新數組長度 array->length = new_length; // 釋放舊數組 kfree(*array_ptr); // 更新指向數組的指針 *array_ptr = array; } // 打印數組內容 void print_int_array(struct variable_int_array *array) { for (size_t i = 0; i < array-?>length; i++) { printk(KERN_INFO "%d ", array->data[i]); } printk(KERN_INFO "n"); } // 內核模塊初始化函數 static int __init my_module_init(void) { struct variable_int_array *my_array = create_int_array(2); if (!my_array) { // 處理錯誤 return -ENOMEM; } // 添加一些值 add_int_to_array(&my_array, 10); add_int_to_array(&my_array, 20); // 打印數組 print_int_array(my_array); // 銷毀數組 destroy_int_array(my_array); return 0; } // 內核模塊退出函數 static void __exit my_module_exit(void) { // 清理工作(如果有的話) } // 注冊模塊初始化和退出函數 module_init(my_module_init); module_exit(my_module_exit); // 定義模塊許可證 MODULE_LICENSE("GPL");

在這個例子中,忽略內核模塊相關部分,重點看結構體variable_int_array相關幾個函數。

我們定義了一個名為variable_int_array的結構體,它包含一個length字段和一個零長度數組data。使用create_int_array函數來分配內存并初始化這個結構體,同時使用destroy_int_array函數來釋放內存。add_int_to_array函數允許我們向數組中添加新的整數,它會動態地重新分配內存以容納新增加的元素。最后,print_int_array函數用來打印輸出出結構體中整數動態數組成員值。

下面具體來看看重點代碼的實現。

create_int_array函數創建一個新的可變長度整數數組的結構體variable_int_array,函數形參initial_length是要創建數組初始長度。第13行使用kmalloc動態分配結構體初始內存空間,這里包括結構體本身和初始長度為initial_length的整數數組空間。第24行就是把initial_length,也即是初始數據長度值存到結構體length成員中,因為長度不是0了而是initial_length。

destroy_int_array就是調用kfree釋放上面創建的內存空間,這個比較簡單。

重點看看add_int_to_array(struct variable_int_array **array_ptr, int value)函數,這個函數就是將一個新的整數值動態添加到數組中,這也是最麻煩的過程。

第一個形參是結構體array_ptr,是個二級指針,指向舊的結構體內存首地址,注意這個指針變量后面新分配內存空間地址要存入其中。第二個形參value是被添加的新的整數值。

第43行是將舊的結構體首地址存到array指針中。

第44行new_length暫時保存數組長度。

第47行是分配新的內存空間,并將首地址存入array變量,注意從此以后array指向新空間。因為數組新加了一個整數,所以空間變大,要重新分配,新分配的空間大小包括之前舊的結構體長度和新添加的一個整數的空間大小。

第59行是將舊的數組數據拷貝到新的數組空間中。

第62行就是新的整數值添加到新數組空間最后一個位置,到此數組空間數據更新完成。

第66行更新結構體的length成員為new_length,其實就是加了個1。

第69行,釋放之前舊結構體的所有內存,因為長度增加分配了新內存了。

第72行就是將新空間地址賦給array_ptr指針變量,這是讓指向舊結構體首地址的指針指向新的結構體首地址了,到此就結束了。

總結

簡單來說,零長度數組就是一個長度為0的數組。但在編程中,它常常被用作一個占位符,或者作為一個結構體的最后一個元素,這樣可以在結構體中靈活地存儲更多的數據。

那么,零長度數組有什么價值和意義呢?

靈活性:零長度數組允許我們在不知道具體需要多少存儲空間的情況下,先分配一個基本的結構體。這樣,我們可以在后續的程序執行中,根據需要動態地添加數據到這個零長度數組中。這種靈活性對于處理可變大小的數據非常有用。

內存效率:通過動態地分配內存給零長度數組,我們可以避免一開始就分配過多的內存,這樣可以更加高效地利用內存資源。只有當我們確實需要額外的存儲空間時,才會分配額外的內存。

簡化代碼:在某些情況下,使用零長度數組可以簡化代碼結構。比如,我們可以將一些相關的數據都放在一個結構體中,而零長度數組可以作為這個結構體的最后一個元素,用于存儲額外的數據。這樣,我們可以更方便地管理和操作這些數據。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5046

    文章

    18823

    瀏覽量

    298719
  • 內核
    +關注

    關注

    3

    文章

    1337

    瀏覽量

    40087
  • Linux
    +關注

    關注

    87

    文章

    11125

    瀏覽量

    207937
  • 內存
    +關注

    關注

    8

    文章

    2904

    瀏覽量

    73554
  • C語言
    +關注

    關注

    180

    文章

    7575

    瀏覽量

    134226
收藏 人收藏

    評論

    相關推薦

    嵌入式系統串口通信幀的同步方法

    制下面介紹一下簡化的串口通信數據幀結構,以便分析說明嵌入式系統串口通信過程的幀同步方法。 假定串口發送的數據幀結構為: 其中:包頭用于同步,一般是一個或多個ASCII字符,本文中假定數據幀同步頭有2
    發表于 10-09 19:17

    怎么才能在使用ss集線器時丟失零長度數據包?

    上的每次讀之前都有一個寫在端點0x01上的操作,它的長度是預先知道的。讀取端點0x82沒有可預測長度,因此FPGA每20毫秒生成一個零長度,以完成當前事務并喚醒主機。下面是我在主機側啟
    發表于 10-18 10:45

    systemd定時器的基本操作方法

    定時器任務作為嵌入式系統中常見的應用,systemd 定時器為用戶提供更多的可配置功能以及優化選項。本文列舉了 systemd 定時器基本操作方法,以及和cron 對比,幫助用戶更快得使用。更多的技術細節和功能請參考下面的鏈接內容。
    發表于 01-01 07:37

    如何配置嵌入式服務器

    嵌入式Web服務器每個Spring Boot Web應用程序都包含一個嵌入式Web服務器。此功能會導致許多操作方法問題,包括如何更改嵌入式服務器以及如何配置
    發表于 10-27 08:35

    嵌入式操作系統Linux 的串口應用編程

    針對嵌入式Linux操作系統的特點,分析在該系統下串行通信口編程控制的方法,總結程序設計的步驟; 在嵌入式Linux 系統上, 編寫控制程序, 成功地實現
    發表于 05-14 14:34 ?28次下載

    汽車電子嵌入式操作系統

    汽車電子嵌入式操作系統
    發表于 10-30 16:07 ?9次下載
    汽車電子<b class='flag-5'>中</b><b class='flag-5'>嵌入式</b><b class='flag-5'>操作</b>系統

    關于 Java 數組的 12 個最佳方法

    下文加介紹的是stackoverflow關于數組方法的相關問題中,獲得最多票數的12個數組操作方法
    發表于 01-29 09:45 ?867次閱讀

    Java數組的基本操作方法整理

    本文主要介紹了Java數組的基本操作方法整理,是Java入門學習的基礎知識。數組是具有相同數據類型的一組數據的集合,Java支持多為數組
    發表于 01-29 10:15 ?1159次閱讀

    基于μC/OS嵌入式操作系統的嵌入式數據管理設計

    較高要求,只能應用在比較高端的嵌入式系統。在低端的嵌入式系統,傳統的數據管理方法是對數據存儲空間按順序編號,數據存儲與刪除均根據編號順序
    發表于 10-09 16:24 ?1182次閱讀
    基于μC/OS<b class='flag-5'>嵌入式</b><b class='flag-5'>操作</b>系統的<b class='flag-5'>嵌入式</b>數據管理設計

    嵌入式操作系統

    參考:[1] 《嵌入式系統軟件及操作系統》1、嵌入式操作系統的功能在嵌入式系統工作的
    發表于 10-21 11:21 ?10次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>操作</b>系統

    嵌入式操作系統

    2.2 實時操作系統的評價指標三、基于Linux的嵌入式操作系統3.1 ARMLinux簡介3.2 uCLinux簡介四、嵌入式操作系統設計
    發表于 11-03 18:36 ?46次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>操作</b>系統

    C語言開發可能會用到的GNU

    ? ? 為了方便使用,GNU C在標準C語言的基礎上進行了部分方便開發的擴展。 這里講解一些開發可能會用到的,或者使用頻率比較高的內容。 零長度數組和變量長度數組 ? GNU C 允許使用
    的頭像 發表于 11-17 10:41 ?1527次閱讀

    0長度數組不占用存儲空間

    由于0長度數組是GNU C的擴展,有一些巧妙編寫的詭異代碼,其執行結果就是依賴于編譯器和優化策略的實現的,我們來看看以下代碼。
    的頭像 發表于 09-28 15:18 ?704次閱讀
    0<b class='flag-5'>長度數組</b>不占用存儲空間

    什么是嵌入式操作系統?

    嵌入式操作系統通常在嵌入式系統工作。嵌入式系統是支持機器的計算機。它在更大的機器上執行一項任務。示例包括汽車
    的頭像 發表于 12-23 15:33 ?7310次閱讀
    什么是<b class='flag-5'>嵌入式</b><b class='flag-5'>操作</b>系統?

    零長數組如何使用定長包定義數據緩沖區

    零長數組 請先思考以下問題: C語言中,數組長度是否可以為0? 如果要接收一個不定長數據包,你會如何定義數據緩沖區? 第一個問題 : 在標準C語言中,沒有長度為0的
    的頭像 發表于 09-27 14:58 ?583次閱讀