cpu是如何拿到所要的資料的呢?靠位址線(address)來選擇到所要的資料,所以位址線有多少條關係到總儲存數量的大小,一顆cpu有多少位址線是不一定的,未必一定要8/16/32,Microchip有24bit定址的cpu,Arm7雖然是32bit的cpu,但是他的核心定址能力只有到26bit(64M),超出會引發錯誤的例外發生。
.
一般來說pointer會依定址能力的寬度來分配大小,是設計compiler公司來決定的,只要足以存取到這顆cpu能定址到的位址就可以了,例如8051定址能力是16bit,可是這顆cpu擁有好幾個不同記憶體區塊,就需要多一個byte來指定到底是在哪裡,所以pointer在8051就是3bytes的大小,而Arm7一般來說都是32bit大小。
.
“char *”的意思是資料為有正負號8bit的pointer,”unsign long *” 為無號32bit的pointer,那(void *)呢?就是無型別。
char *ptr8;
unsigned long *ptr32;
void * ptrx;
ptr32 = ptr8; // 會引發compiler型別錯誤
ptrx = ptr8; // 不會引發錯誤,最多只有警告。
*ptr8 = 100; // 在一個8bit寬的地方填入100
*ptrx=100; // 錯誤,因為不知道目的地到底有多大。
.
那到底void *有甚麼用呢?用處很大ㄡ,”轉手與暫存用”,例如你寫了一個function要多種用途,尤其是具有擴展性的程式:
typedef struct {
char type;
ooxx....
} OBJ_A;
.
typedef struct {
char type;
ccdd...;
} OBJ_B;
.
enum { OBJ_A_LABLE, OBJ_B_LABLE };
OBJ_A MyObjA = { OBJ_A_LABLE, . . . .};
OBJ_B MyObjB = { OBJ_B_LABLE, . . . .};
.
void ObjParser(void *obj)
{
char *type_p = (char*)obj;
switch(*type_p)
{
case OBJ_A_LABLE:
{
OBJ_A *obj_p = (OBJ_A *)obj;
// ....process
}
break;
case OBJ_B_LABLE:
{
OBJ_B *obj_p = (OBJ_B *)obj;
// ....process
}
break;
. . . . . . .
}
}
void main(void)
{
ObjParser((void*)&ObjA);
ObjParser((void*)&ObjB);
}
當然引數也可以轉換成function pointer,不同傳回值與不同引數的function pointer都可以因為有void *的引數而被統一起來,將來也很容易擴展這個函式,整個程式不會因為功能變多而變得要修改許多地方,甚至可以function pointer與data pointer共用同一個void *obj,你只需要在你的switch case增加一個項目就可以了,善用void*,是可以讓程式穩定度與擴展性提升的方法之一,寫C程式要如何善用pointer是非常重要的,學校不知為什麼都不太願意交代清楚。