<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 設計應用 > 零長(cháng)度數組沒(méi)有意義?那是你不懂!看Linux內核中怎么高級玩它?

零長(cháng)度數組沒(méi)有意義?那是你不懂!看Linux內核中怎么高級玩它?

作者: 時(shí)間:2024-04-02 來(lái)源: 收藏

C語(yǔ)言零長(cháng)度,聽(tīng)起來(lái)可能有點(diǎn)奇怪,因為它沒(méi)有分配內存空間,無(wú)法存儲數據。但實(shí)際上,零長(cháng)度中隨處可見(jiàn)。

本文引用地址:http://dyxdggzs.com/article/202404/457117.htm

零長(cháng)度的定義

首先,我們要明白什么是零長(cháng)度數組。簡(jiǎn)單來(lái)說(shuō),零長(cháng)度數組就是一個(gè)長(cháng)度為0的數組,也就是說(shuō)不包含任何元素的數組。零長(cháng)度數組在C99標準中引入,并在C11中得到進(jìn)一步的支持。其定義很簡(jiǎn)單,就是一個(gè)大小為0的數組。例如:

int a[0];

中,零長(cháng)度數組通常不會(huì )直接這樣使用,而是作為結構體中最后一個(gè)元素,配合動(dòng)態(tài)內存分配來(lái)使用。

零長(cháng)度數組在中的應用案例

在Linux內核中,經(jīng)??梢钥吹搅汩L(cháng)度數組被用作結構體末尾的占位符,以表示結構體的可變長(cháng)度部分。例如,一個(gè)表示網(wǎng)絡(luò )套接字的struct sockaddr結構體可能如下所示:

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

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

struct sockaddr {  
   sa_family_t    sa_family;    // 地址家族  
   char            sa_data[0];  // 可變長(cháng)度部分,實(shí)際使用時(shí)會(huì )動(dòng)態(tài)分配  
};

在實(shí)際應用中,內核代碼會(huì )結合動(dòng)態(tài)內存分配來(lái)設置需要的的sa_data長(cháng)度,并填充相關(guān)的數據。零長(cháng)度數組可以與kmalloc、vmalloc等內存分配函數結合使用,來(lái)實(shí)現這種動(dòng)態(tài)分配,所以有人也把零長(cháng)度數組稱(chēng)為柔性數組。

如何具體實(shí)現結構體動(dòng)態(tài)內存分配?

在Linux內核或其他C語(yǔ)言編寫(xiě)的底層系統中,零長(cháng)度數組經(jīng)常被用作靈活的數據結構的一部分,特別是在需要動(dòng)態(tài)增長(cháng)或縮小的數組中。以下是一個(gè)簡(jiǎn)單的示例,展示了如何在內核編程中使用零長(cháng)度數組來(lái)實(shí)現一個(gè)可變長(cháng)度的整數數組:

#include// 包含printk等內核函數
#include// 包含kmalloc和kfree等內存管理函數
 
// 定義一個(gè)結構體,用于表示可變長(cháng)度的整數數組  
struct variable_int_array {  
   size_t length;         // 數組當前長(cháng)度  
   int data[0];           // 零長(cháng)度數組,實(shí)際數據存儲在這里  
};  
 
// 創(chuàng )建一個(gè)新的可變長(cháng)度整數數組  
struct variable_int_array *create_int_array(size_t initial_length) {  
   // 分配內存,包括結構體本身和初始長(cháng)度的整數數組  
   struct variable_int_array *array = kmalloc(  
       sizeof(struct variable_int_array) + initial_length * sizeof(int),  
       GFP_KERNEL  
   );
 
 
   if (!array) {  
       // 內存分配失敗  
       return NULL;  
   }  
 
   // 初始化數組長(cháng)度  
   array->length = initial_length;  
 
   // 返回新創(chuàng )建的數組  
   return array;  
}  
 
// 銷(xiāo)毀一個(gè)可變長(cháng)度整數數組  
void destroy_int_array(struct variable_int_array *array) {  
   if (!array) {  
       // 空指針檢查  
       return;  
   }  
 
   // 釋放內存  
   kfree(array);  
}  
 
// 向數組中添加一個(gè)新的整數  
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;  
 
 
   // 更新數組長(cháng)度  
   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);  
 
   // 銷(xiāo)毀數組  
   destroy_int_array(my_array);  
 
   return 0;  
}  
 
// 內核模塊退出函數  
static void __exit my_module_exit(void) {  
   // 清理工作(如果有的話(huà))  
}  
 
// 注冊模塊初始化和退出函數  
module_init(my_module_init);  
module_exit(my_module_exit);  
 
// 定義模塊許可證  
MODULE_LICENSE("GPL");

在這個(gè)例子中,忽略?xún)群四K相關(guān)部分,重點(diǎn)看結構體variable_int_array相關(guān)幾個(gè)函數。

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

下面具體來(lái)看看重點(diǎn)代碼的實(shí)現。

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

destroy_int_array就是調用kfree釋放上面創(chuàng )建的內存空間,這個(gè)比較簡(jiǎn)單。

重點(diǎn)看看add_int_to_array(struct variable_int_array **array_ptr, int value)函數,這個(gè)函數就是將一個(gè)新的整數值動(dòng)態(tài)添加到數組中,這也是最麻煩的過(guò)程。

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

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

第44行new_length暫時(shí)保存數組長(cháng)度。

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

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

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

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

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

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

總結

簡(jiǎn)單來(lái)說(shuō),零長(cháng)度數組就是一個(gè)長(cháng)度為0的數組。但在編程中,它常常被用作一個(gè)占位符,或者作為一個(gè)結構體的最后一個(gè)元素,這樣可以在結構體中靈活地存儲更多的數據。

那么,零長(cháng)度數組有什么價(jià)值和意義呢?

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

內存效率:通過(guò)動(dòng)態(tài)地分配內存給零長(cháng)度數組,我們可以避免一開(kāi)始就分配過(guò)多的內存,這樣可以更加高效地利用內存資源。只有當我們確實(shí)需要額外的存儲空間時(shí),才會(huì )分配額外的內存。

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



關(guān)鍵詞: 數組 Linux 內核

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>