《深入理解計算機系統》讀書筆記(ch2)+ C 泛型
阿新 • • 發佈:2018-10-27
tex byte 指向 get 讀書筆記 class its n) 支持
本章主要介紹各類型的機器表示,Stanford的CS107的lec2和lec3有精彩解釋,比看書快(當作書中只是的cache吧)。
lec4中介紹的C裏面如何使用泛型(沒有template, reference)的技巧在此記錄一下:
/*普通的swap函數*/
void swap(int *ap, int *bp) { int temp = *ap; *ap = *bp;*bp = temp; } int x = 7; int y = 117; swap(&x, &y);//x=117, y=7
/*泛型swap函數, 錯誤實現*/
void swap(void *vp1, void *vp2)
{
void temp = *vp1; //不能dereference void指針,因為不知道指針類型,也就是不知道何時停止
*vp1 = *vp2;
*vp2 = temp;
}
/*泛型swap函數,正確實現*/
void swap(void *vp1, void *vp2, int size)//關鍵是交換bit pattern
{
char buffer(size);//需要編譯器支持入參定義數組大小,char類型不重要,只是復制bit pattern。編譯器不支持換用malloc即可
memcpy(buffer,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buffer,size);
}
//對普通變量使用swap
int x=7,y=117;
swap(&x,&y,sizeof(int));
//對指針變量使用swap
char *husband = strdup("Fred");
char *wife = strdup("Wilma");
swap(&husband, &wife, sizeof(char *));
對比template實現的優勢:不會導致代碼膨脹(不同類型的template會在二進制中復制自己的版本)。
劣勢:內存管理復雜。
先介紹一下泛型實現的linear search:
//linear search for int array int lsearch(int key, int array[], int size) { for (int i=0 ;i<size; i++) { if( array[i] == key){ return i; } } } //generic linear search,只對基本類型有效,struct等可包含指針的類型無效void *lsearch( void *key, void *base, int n, int elemSize) { for(int i=0; i<n; i++) { void *elemAddr = (char *)base + i*elemSize;//void star hack,將指針算數等價為普通算數運算,因為char的大小為1 if(memcmp(key,elemAddr,elelSize)==0){ return elemAddr; } } } //generic linear searchvoid *lsearch(void *key, void *base, int n, int elemSize, int (*cmpFn)(void*,void*)) { for(int i=0; i<n; i++)
{
void *elemAddr = (char *)base + i*elemSize;//void star hack,將指針算數等價為普通算數運算,因為char的大小為1
if(cmpFn(key, elemAddr) == 0){//hook
return elemAddr;
}
}
return NULL;
}
//use lsearch for int
int array[] = {4,2,3,7,11,6};
int size = 6;
int number = 7;
int IntCmp(void *elem1, void *elem2)
{
int *ip1 = elem1;
int *ip2 = elem2;
return *ip1-*ip2;
}
int *found = lsearch(&number,array,6,sizeof(int),IntCmp);
if(found==NULL)printf("not found");
//use lsearch for char*
char *notes[] = {"Ab","F#","B","Gb","D"};
char *favoriteNote = "Eb";
int StrCmp(void *elem1, void *elem2)
{
char *s1 = *(char **)elem1;// 先說明指針類型,然後解引用,得到一個char *
char *s2 = *(char **)elem2;
return strcmp(s1,s2);
}
char **found = lsearch(&favoriteNote, notes, 5, sizeof(char *), StrCmp);
//實際上lsearch和bsearch都是內建泛型函數,bsearch接口如下
void *bsearch(void *key, void *base, int n, int elemSize, int (*cmp)(void *, void *));
C中同樣沒有類的概念,結構體中的變量只能是public,要實現一個類似Stack的數據結構需要程序員自己註意用法(不要直接使用struc中的數據成員,而是使用配套的“方法”)
typedef struct{ int *elems; int logicalLen; int allocLen; }Stack;//12 bytes void StackNew(Stack *s){ s->logicalLen = 0;
s->allocLen = 4;
s->elems = malloc(4*sizeof(int));
assert(s->elems != NULL); } void StackDispose(Stack *s){
free(s->elems);//be careful, s->elems shouldn‘t be null
} void StackPush(Stack *s, int value){
if(s->logicalLen == s->allocLen){//空間不足時分配雙倍空間
s->allocLen *=2;
s->elems = realloc(s->elems,s->allocLen*sizeof(int));//記得捕捉返回值,若地址變動可能指向死內存
//fun fact: C++ doesn‘t have its own realloc
assert(s->elems!=NULL);
}
s->elems[s->logicalLen] = value;
s->logicalLen++;
} void StackPop(Stack *s){
assert(s->logicalLen>0);
s->logicalLen--;
return s->elems[s->logicalLen];
} //使用Stack Stack s;//分配內存 StackNew(&s); for(int i = 0; i<5; i++){ StackPush(&s, i); } StackDispose(&s);
下面介紹泛型實現的stack
typedef struct{ void* elems; int logicalLen; int allocLen; int elemSize; }Stack; void StackNew(Stack *s, int elemSize){ assert(s->elemSize>0); s->elemSize = elemSize; s->logicalLen = 0; s->allocLen = 4; s->elems = malloc(4*elemSize); assert(s->elems != NULL); } void StackDispose(Stack *s){ free(s->elems); } static void StackGrow(Stack *s){//static聲明的函數只能在本文件中被使用 s->allocLen *=2; s->elems = realloc(s->elems, s->allocLen*s->elemSize ); } void StackPush(Stack *s, void *elemAddr){ if(s->logicalLen == s->allocLen) StackGrow(s); void *target = (char*)elems + s->logicalLen*s->elemSize; memcpy(target,elemAddr,s->elemSize); s->logicalLen++; } void StackPop(Stack *s, void *elemAddr){ void *source = (char*)s->elems + (s->logicalLen-1)*s->elemSize; memcpy(elemAddr, source, s->elemSize); s->logicalLen--; }
《深入理解計算機系統》讀書筆記(ch2)+ C 泛型