c c 學習筆記 12

2022-02-22 02:43:20 字數 2503 閱讀 6279

此次為練習實踐記錄,講解用純c模擬乙個c++的int型別的stack。

因為在純c中沒有class關鍵字,也沒有public、private,但是有struct,現在已最接近的方式實現,宣告如下:

1 typedef struct

2 stack;

在純c中typedef是必須的,但是在c++中是不必要的。從技術上來講,以上3個域都是暴露在外的,都是隱含為public的。我們可以將stack宣告為區域性變數,編譯器知道這種型別佔12位元組,但是我們不應該直接操縱這些資料,應該使用函式對它們進行操作。我們要將任何類的結構型別看作是黑盒,並通過函式來操作這12位元組。因此要有乙個建構函式、析構函式、pop函式(彈出棧)、push函式(壓入棧),宣告如下:

1

void stacknew(stack *s);23

void stackdispose(stack *s);45

void stackpush(stack *s, int

value);67

int stackpop(stack *s);

當呼叫乙個類的建構函式的時候,函式要訪問到this指標,函式會將this作為諸如第-1個引數或者作為乙個隱含引數在其他引數傳入之前傳入。以下先給出如何呼叫的**:

1

stack s;

2 stacknew(&s);

3for(int i = 0; i < 5; i++)

47 stackdispose(&s);

接下來根據以上的**,一步步往下實現。首先是stacknew(建構函式)實現如下:

1

void stacknew(stack *s)

2

malloc是乙個動態分配記憶體的函式,是乙個相當於new的比較早的申請記憶體的方式。在純c中沒有new、delete,有名為malloc的記憶體分配器。new操作符會隱含的考慮到資料型別,因為實際的表達是可能為new int[4],malloc函式用乙個引數來指定需要的原始位元組的大小並將申請到的空間作為陣列或者你構建的結構。因此我們需要4個int大小的記憶體,因此就要傳入4 * 每個int單元布局的大小,malloc會在堆中查詢這樣乙個記憶體塊,然後返回它的位址(通常情況下都會返回位址)。如果擔心返回null,可以加入乙個assert巨集,**如下:

assert( s -> elements != null );

因為如果由於某種原因導致malloc執行失敗(實際是很少的),記憶體不足而失敗或是你在某些不允許釋放的記憶體上呼叫了free函式(該函式後面會講到),這樣就會把真個記憶體分配器搞得一團糟。以上的**表明可能該地方可能會出現問題,而不是最終造成段錯誤或者匯流排錯誤或者不明原因的崩潰,而讓你無法跟蹤到錯誤發生的地方。

接下來是stackdispose(析構函式),實現如下:

1

void stackdispose(stack *s)

2

因為除了stacknew地方以外,沒有其他地方為stack變數分配空間,假設stack變數本身的空間已經被分配好並且它的位址作為引數被stacknew指定,因此你不知道這個變數的空間是否動態申請的。前面的stack變數s是區域性變數,它不是動態申請的。所以我們不需要釋放s本身所佔的記憶體。

stackpush(壓入棧),該函式不僅僅是將乙個int型別新增到陣列的末尾,而是能夠在當申請空間已經飽和時,適當的將申請的空間進行擴充套件(2n倍擴充),變得更大,然後將舊的陣列複製過來,並將舊的陣列清理掉,實現如下:

void stackpush(stack *s, int

value)

s->elements[s->logicallen++] =value;

}

對於realloc在c++中沒有與它等價的函式,它會嘗試獲取傳入的指標值,然後先檢查已經分配了的記憶體塊是否可以調整大小,如果可以則記錄下擴充套件了的記憶體塊已經包含了更多的空間並返回同樣的位址,不行的話則尋找新的記憶體塊,並將陣列複製過去,然後釋放掉舊的陣列記憶體塊並返回最終的位址。第二個引數是將記憶體塊調整到這個引數的大小。如果不將s->elements = 返回的位址,那麼s->elemetns則是原始的位址,當操作後的位址發生改變,在呼叫s->elements的時候,引用的可能是**給堆管理器的記憶體。如果realloc操作失敗,會返回null,且原來的記憶體塊並不會被釋放。我們仍然可以在最後加入乙個assert,來用簡單的出錯資訊提示使用者,擴充套件失敗,請嘗試其他的操作等。

最後stackpop(彈出棧),函式還是挺簡單的,實現如下:

1

int stackpop(stack *s)

2

隨著不斷的彈出棧,我們所需要的空間慢慢的變小了,如果想把多餘的空間還給堆,根據對於realloc實現的理解,因為編譯器希望能夠執行得越快越好,通常編譯器會忽略縮小陣列的請求,只要記憶體大小滿足需求編譯器並不在乎多申請了的一點空間,你仍然可以使用想要的空間大小,但是實際的空間大小仍然為你保留著,因為這樣能更快的執行。

基本上到這裡已經將**實現並且講解完了,時間也很晚了,就到這裡吧,呵呵,明天早上繼續學習,加油!

學習筆記12

sql server提供了兩種索引 聚集索引和非聚集索引。其中聚集索引表示表中儲存的資料按照索引的順序儲存,檢索效率比非聚集索引高,但對資料更新影響較大。非聚集索引表示資料儲存 在乙個地方,索引儲存在另乙個地方,索引帶有指標指向資料的儲存位置,非聚集索引檢索效率比聚集索引低,但對資料更新影響較小。聚...

C C學習筆記

1.儲存型別 標準c語言為變數 常量 函式定義了4種儲存型別 extern,auto,static,register,它們分別用乙個關鍵字 儲存型別說明符 來說明。這4種儲存型別可分為兩種生存期限 永久的 即整個程式執行期間都存在 extern和static 和臨時的 即暫時儲存在堆疊和暫存器中 a...

C,C 學習筆記

1.求a的n次方 標頭檔案pow a,n a,n都為double 2.關於指標的一些小測試 includeusing namespace std int main int a 8 int m 3 cout 3.sort位於 algorithm 中,sort p,p n 預設公升序排列。4.inclu...