發表文章

【轉載】Data structure的對齊(alignment)

來源 變數的宣告,會配置其所需的記憶體。每種變數所需的大小不一樣,比如說char是1 bytes,int 是4 bytes,double則是8 bytes。如果是這樣,那這些大小在記憶體中是如何擺放呢?是直覺的一個接一個放嗎?其實不然。這牽扯到performance / efficiency的問題! 在32 bits的架構上,一次的資料存取也就是32 bits (4 bytes)。而這4 bytes 不是隨便從哪個點抓都可以,而是以4 bytes為單位,不管需要的是其中那個byte,就抓那4個bytes。比如說,抓第0,4,8 ,12....等,而不會是從3,7,9開始抓4個bytes。 這代表什麼呢?這表示了對齊 (alignment)的重要,因為會影響到幾次才抓的完。如果要抓一個4 bytes 的int,而這個int是從6擺到10,那就表示要抓兩次,自然效能較差了。因此,在struct的宣告是存在對齊這件事的。見下例: #include <stdio.h> int main(int argc, char* argv[]) {         struct align_test         {                 char x; //1 byte                 int y;  //4 bytes                 short int z;  //2bytes         };   ...

【轉載】動態空間分配

來源 動態空間分配 所謂動態空間分配指的是,在執行期間由程式向作業系統或程式庫要求後才分配的空間,這塊記憶體區域稱為Heap(堆積)。C語言的動態空間分配主要透過malloc和free兩函數來處理。這兩個函數的宣告如下: void *malloc(size_t size); void free(void *ptr); 透過malloc()所分配出來的空間必須由使用者呼叫free()才能歸還給系統。初學者常犯的錯誤之一,就是忘了用free()歸還空間,這會造成程 式佔用太多記憶體,此現象稱為memory leakage。相反的,如果空間已用free()歸還了,卻還試著去使用那塊記憶體,則會發生Segmentation Fault (core dumped)的錯誤。 Linked Stack typedef struct items { int data; struct items *link; } ITEM; typedef struct stack { ITEM *top; } STACK; void initStack(STACK *s) { s->top = NULL; } void pushStack(STACK *s, int y) { ITEM *x; // x will point to the new ITEM x = (ITEM *) malloc(sizeof(ITEM)); // allocate memory for the new ITEM x->data = y; // store data x->link = s->top; // x->link points to where s->top points s->top = x; // stack's top points to x } int popStack(STACK *s) { ITEM * x = s->top; int d = x->data; s->top = s->top->link; free(x); return d; } int stackIsEmpty(ST...

【轉載】用於struct的運算符號

來源 在如下的結構定義裡,next前面的*不可省略,否則就遞迴定義了,Compiler將無法決定struct list的大小。 struct list { int data; struct list *next; // a pointer to struct list }; struct list listOne, listTwo, listThree; listOne.next = &listTwo; listTwo.next = &listThree; // 以下想要由listOne設定到listThree的data listOne.next.next.data = 0; // 這不合法, 因為.的左邊必須是struct,不可以是pointer (*(*listOne.next).next).data = 0; // 這樣寫才對     你會發現上面的例子中, 如果struct裡面有pointer to struct, 而我們想要用該pointer來存取結構成員時, 就必須很小心的用*和()來表達。由於結構成員包括指向結構的指標(define a pointer to struct in a struct), 是很常見的事情, 這樣的(*(*listOne.next).next).data語法既難寫又難懂, 因此C語言定義了->運算符號。此符號的左邊是一個pointer to struct, 右邊則是該pointer指到的結構成員。->為第一優先權左結合, 因此 (*(*listOne.next).next).data = 0; //這樣寫才對 listOne.next->next->data = 0; // 這樣寫更漂亮

【轉載】static修飾詞

(來源)http://www.csie.nctu.edu.tw/~skyang/static.zhtw.htm 在全域變數或函式的宣告之前加上 static,就讓它們不能跨 .cpp 檔使用,如下例中的 compare_grade( )它的目的僅在於提供給下面的 qsort( ) 使用,所以在它函式宣告之前加了 static,這麼一來它就只能在這個 .cpp 檔案中有效,在其他的 .cpp 檔案中就算以 extern 來援用它也不可以,另一方面,在其他的 .cpp 檔案中就算有同名的 compare_grade( ) 函式也沒關係。 #include <math.h> #include <stdlib.h> #include "GradeList.h" static int compare_grade(const void *ptr1, const void *ptr2) { float f1 = *((float *)ptr1); // 把 ptr 轉型成 (float *)再取值 float f2 = *((float *)ptr2); if (f1 > f2) { return 1; } / / 如果 f1 比較大就傳回正數 else if (f1 < f2) { return -1; } return 0; } // 用 compare_grade( ) 比較 grade 中每個 float,由小到大排序: void GradeList::sort_grade_list(void) { qsort(grade, students, sizeof(float), compare_grade); } 另一個與這樣的 static 相對的修飾詞是 extern,這個修飾詞用來讓你使用其他檔案的全域變數與函式,在變數宣告或函式原型宣告前加上 extern,則編譯器不會產生新變數或函式,而是在連結(linking)階段才使用其他檔案中的變數或函式,例如: A.cpp int curUsers = 5; B.cpp extern int curUsers; / / 不可以再給初始值 修飾函式中的區域變數 以下...

【轉載】C/C++中的volatile使用時機?

(原作者)http://freestyler.pixnet.net/blog/post/23872864-c-c%2B%2B%E4%B8%AD%E7%9A%84volatile%E4%BD%BF%E7%94%A8%E6%99%82%E6%A9%9F%3F C/C++ 的volatile C/C++中的volatile使用時機? .不知各位對volatile(揮發性的)這個字陌不陌生? 我相信大家在一些程式或多或少都看  過這個字眼, 但是究竟要在何種場合用它呢? .當然一定是有需要, C/C++才會有這個保留字, 否則只是增加programmer的困擾而已 .有2兩個場合(I/O & multithread program), 供各位參考! .請大家check自己的程式中(尤其是第2個場合), 若有的話請記得加上volatile 1. I/O, 假設有一程式片斷如下        U8   *pPort;        U8   i, j, k;              pPort = (U8 *)0x800000;           i = *pPort;            j = *pPort;            k = *pPort;         以上的i, j, k很有可能被compiler最佳化而導致產生        i = j = k = *pPort;     的code, 也就是說只從pPo...

指標

int x, y, *ip, *iq; x = 2; /* 敘述 1 */ y = x + 3; /* 敘述 2 */ ip = &x; /* 敘述 3 */ iq = ip; /* 敘述 4 */ *iq = *ip + y; /* 敘述 5 */ 敘述四之指標 iq 與指標 ip 同時指向 x ,因此 *iq 與 *ip 和 x 是相等的。

指標

    int *ip;       /* ip 為一指標變數 */     int x = 2, y;     ip = &x;     y  = *ip + 1;  /* 與 y = x + 1; 相同 */     /* 其輸出結果為: 2 65524 2 65524 3 65522 */  y=*ip+1的*ip為間接取值, 不是取ip的值,而是取ip所指向的記憶體位址的值,因此該敘述與y=x+1相同