我們說我有一個陣列
int size=6;
int a[size]={0, 1, 2,3,4,5}。
而我想洗掉k=3元素。
for(i=k;i<size-1; i )
a[k]=a[k 1]。
size=size-1。
在這里,我只是洗掉了索引k的元素,可以肯定的是這個值不會出現在陣列中,但是如果不在陣列中,那么資料在哪里,這個值。
uj5u.com熱心網友回復:
沒有什么被洗掉。
這一行a[k]=a[k 1];將a[k]的值設定為a[k 1]的值。
因此,如果陣列以{0,1,2,3,4,5}開始,并且k是3,那么之后陣列就持有{0,1,2,4,4,5}。
uj5u.com熱心網友回復:
你不能 "洗掉 "陣列中的專案,只是用其他資料覆寫它們。C語言接近于硬體,在物理RAM中,單元格不存在 "洗掉 "的狀態,它必須始終保持一個值。
因此,洗掉一個專案是通過將你想洗掉的那個專案后面的所有專案向前移動一步來完成的(這樣做的效率相當低)。但分配的大小仍將是相同的。所以你需要一個計數器變數來跟蹤實際使用的資料大小。
給定一個陣列
int array[]={0,1,2,3,4,5};那么專案的數量是
sizeof array / sizeof *array;size_t items = sizeof array / sizeof *array。items將是上述的計數器變數。我們希望在某個索引處洗掉一個專案:
size_t index = 3。那么,你想洗掉的專案后面的塊的大小就表示為:
size_t size_to_move = (items-index-1) * sizeof *array;在32位計算機上是(6-3-1) * 4 = 8位元組。
我們正在同一個陣列內移動資料,這意味著有重疊的記憶體段。在重疊的情況下,我們不能使用
memcpy,所以我們必須使用專門的函式memmove,它在內部使用臨時緩沖區來處理重疊的問題。
給定的資料量為1.5萬,而你的資料量為2.5萬。
完整的例子:
#include <stdio.h>/span>
#include <string.h>
int main()
{
int array[]={0, 1, 2,3,4,5};
size_t items = sizeof array / sizeof *array;
size_t index = 3;
size_t size_to_move = (items-index-1) * sizeof *array;
memmove(&array[index], &array[index 1], size_to_move) 。
items--。
for(size_t i=0; i< items; i )
{
printf("%d", array[i]) 。
}
}
輸出:
0 1 2 4 5
注意,如果我們不使用item--減少專案計數器,我們將得到0 1 2 4 5 5。分配的陣列大小仍然是6,所以我們仍然可以訪問最后一個專案,而那個專案曾經持有5,所以它仍然包含它,因為專案實際上沒有被 "移動",而是被復制。
uj5u.com熱心網友回復:
在C語言中,一個陣列有一個固定的大小。這意味著你既不能向陣列中添加也不能洗掉元素。你只能重寫它們。
在C語言中,陣列有固定的大小。
最接近于動態大小的陣列是一個動態陣列,它可以通過malloc獲得。它后來可以通過realloc來調整大小,但:
- 標準庫可以忽略任何收縮呼叫并保持陣列的最大尺寸 。
- 釋放的記憶體可以回傳給作業系統,以便其他行程可以訪問,也可以保留在當前行程中 。
- 一個擴展呼叫可以涉及現有元素的完整拷貝 。
重新分配動態陣列的確是C語言中常見的習慣,但是你必須意識到它的局限性,不要濫用它。在你的例子中,這將是一種過度的行為。
動態分配的記憶體必須由
free來釋放。在呼叫free之后:
指標被釋放。
指標保持其先前的值,并且被稱為
dangling指標,因為它指向未分配的記憶體,并且取消參考它明確地呼叫了未定義行為(C程式員的地獄...)標準庫的實作可以自由地對釋放的記憶體做它想做的事:
- 它可以回傳給作業系統 。
- 如果可以被recycled,成為可用于以后的
malloc呼叫,甚至成為不再可用的。用于管理動態記憶體的底層演算法并沒有被標準所指定 。
這就是說,一種常見的演算法是與作業系統交換一定大小的頁,并從這些頁中為程式分配記憶體。空的區塊通常被當作一個串列來處理,新釋放的區塊與相鄰的空閑區塊相連接,以盡量使區塊的大小盡可能大。而只有當一個頁面被包含在一個空閑區塊中時,它才能被回傳給作業系統。但這是標準庫的實作者的問題,而不是C程式員的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/334248.html
標籤:
