2010-07-03 44 views
2

我有兩個C函數,它們基本上在堆棧數據結構上運行。這一個將類型OBJ的值推到棧頂,實際上它只是unsigned long。如果需要,堆棧也會生長。如何在一塊內存中的任意位置插入一個值?

OBJ Quotation_push_(CzState *cz, CzQuotation *self, OBJ object) 
{ 
    if ((self->size + 1) > self->cap) { 
     self->items = (OBJ *)CZ_REALLOC(self->items, sizeof(OBJ) * (self->cap + 1) * 2); 
     self->cap = (self->cap + 1) * 2; 
    } 
    self->items[self->size++] = object; 
    return (OBJ)self; 
} 

下一個函數插入一個OBJself->items陣列中的任意位置。儘可能地嘗試,它只是無法正常工作。我在這裏使用了Quotation_push_以虛擬值來獲得自動增長行爲。問題是,我總是在數組末尾看到CZ_NIL虛擬值,我試圖插入的項目只是覆蓋已經在位置上的內容。下面是我到目前爲止有:

OBJ Quotation_insert_(CzState *cz, CzQuotation *self, OBJ object, int pos) 
{ 
    printf("have to move %d OBJ from %d to %d\n", self->size - pos, pos, pos + 1); 
    Quotation_push_(cz, self, CZ_NIL); 
    memmove(self->items + ((pos + 1) * sizeof(OBJ)), self->items + (pos * sizeof(OBJ)), sizeof(OBJ) * (self->size - pos)); 
    self->items[pos] = object; 
    return (OBJ)self; 
} 

我沒有得到任何內存設計缺陷或錯誤,它只是不正常工作。有任何想法嗎?

回答

3

更新:

有兩個問題,無論是在調用memmove

第一個是應該移動的字節數的錯誤。正確的數字是:

sizeof(OBJ) * (self->size - pos - 1) 

省略-1將會實際上搬到一個字節太多,把你的新CZ_NIL對象過去緩衝區的結束。

第二個問題是更大,但更微妙。將整數添加到指針會導致編譯器執行pointer arithmetic,它會自動計算指向的對象的大小。詳情請參閱this question。以下是簡短版本:self->itemsOBJ的數組,因此您不需要在memmove的前兩個參數中包含sizeof(OBJ)

全部放在一起,正確的函數調用是這樣的:

memmove((self->items + pos + 1), 
     (self->items + pos), 
     sizeof(OBJ) * (self->size - pos - 1)); 
相關問題