<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

          零長度數(shù)組沒有意義?那是你不懂!看Linux內(nèi)核中怎么高級玩它?

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

          C語言零長度,聽起來可能有點(diǎn)奇怪,因?yàn)樗鼪]有分配內(nèi)存空間,無法存儲數(shù)據(jù)。但實(shí)際上,零長度中隨處可見。

          本文引用地址:http://www.ex-cimer.com/article/202404/457117.htm

          零長度的定義

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

          int a[0];

          中,零長度數(shù)組通常不會直接這樣使用,而是作為結(jié)構(gòu)體中最后一個(gè)元素,配合動態(tài)內(nèi)存分配來使用。

          零長度數(shù)組在中的應(yīng)用案例

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

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

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

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

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

          如何具體實(shí)現(xiàn)結(jié)構(gòu)體動態(tài)內(nèi)存分配?

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

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

          在這個(gè)例子中,忽略內(nèi)核模塊相關(guān)部分,重點(diǎn)看結(jié)構(gòu)體variable_int_array相關(guān)幾個(gè)函數(shù)。

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

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

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

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

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

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

          第43行是將舊的結(jié)構(gòu)體首地址存到array指針中。

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

          第47行是分配新的內(nèi)存空間,并將首地址存入array變量,注意從此以后array指向新空間。因?yàn)閿?shù)組新加了一個(gè)整數(shù),所以空間變大,要重新分配,新分配的空間大小包括之前舊的結(jié)構(gòu)體長度和新添加的一個(gè)整數(shù)的空間大小。

          第59行是將舊的數(shù)組數(shù)據(jù)拷貝到新的數(shù)組空間中。

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

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

          第69行,釋放之前舊結(jié)構(gòu)體的所有內(nèi)存,因?yàn)殚L度增加分配了新內(nèi)存了。

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

          總結(jié)

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

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

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

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

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



          關(guān)鍵詞: 數(shù)組 Linux 內(nèi)核

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();