網路城邦
上一篇 回創作列表 下一篇   字體:
c語言中void *該如何使用呢?
2009/10/31 21:09:18瀏覽51566|回應2|推薦4

cpu是如何拿到所要的資料的呢?靠位址線(address)來選擇到所要的資料,所以位址線有多少條關係到總儲存數量的大小,一顆cpu有多少位址線是不一定的,未必一定要8/16/32Microchip24bit定址的cpuArm7雖然是32bitcpu,但是他的核心定址能力只有到26bit(64M),超出會引發錯誤的例外發生。

.

    一般來說pointer會依定址能力的寬度來分配大小,是設計compiler公司來決定的,只要足以存取到這顆cpu能定址到的位址就可以了,例如8051定址能力是16bit,可是這顆cpu擁有好幾個不同記憶體區塊,就需要多一個byte來指定到底是在哪裡,所以pointer8051就是3bytes的大小,而Arm7一般來說都是32bit大小。

.

“char *”的意思是資料為有正負號8bitpointer”unsign long *” 為無號32bitpointer,那(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 pointerdata pointer共用同一個void *obj,你只需要在你的switch case增加一個項目就可以了,善用void*,是可以讓程式穩定度與擴展性提升的方法之一,寫C程式要如何善用pointer是非常重要的,學校不知為什麼都不太願意交代清楚。

( 心情隨筆心情日記 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=cchahacaptain&aid=3455063

 回應文章

隆隆岩強森
2018/09/21 21:04
謝謝!


等級:
留言加入好友
計數器的動作
2011/09/05 17:32
抱歉浪費你一點時間,請問計數器的動作. 我是用c語言寫外部計數器, 程式中有一個正數另一個倒數. 正數時是沒問題,可是在倒數時,倒數到114後就有誤動作產生. 可以請教是記憶體的問題嗎? 我是用NXP 單晶片,謝謝
彼得鄧(cchahacaptain) 於 2011-09-06 18:14 回覆:

不好意思,nxp mcp我沒用過,我可能沒辦法直接回答你的問題。

不過我可以提供一下debug的方向,首先誤動作是甚麼一定要確定?mcu的硬體周邊,一般來說有很多設定一定要全部設對才會動作正確,有時候設定是放在某些你想像不到的其他周邊區域。

如果是記憶體內部記憶體,又是大廠,一般來說不太需要考慮到損毀的問題,外部記憶體才需要考慮到線路的問題,但只要寫一個記憶體測試函式就可以確定這個問題,用32bit整數,由零向上加,寫入外部記憶體,所以外部必定是0,1,2,3...增加,再讀回判斷,只要用迴圈來判斷是否是0,1,2,3增加就知道正確與否,千萬不要用8bit整數來做運算,如果外部address的bit8以上有問題,根本看不出來錯誤了。

內建記憶體通常有很多種模式,要小心有沒有出問題。

io腳位如果有overshoot/undershoot發生,有時會讓硬體發生奇怪的事,有時overshoot會連續觸發好幾個中斷,此時如果堆疊不夠大,會發生記憶體overflow的問題,當然電壓不對就更不行了。

軟體程式碼造成誤動作,可能性就更多了,我不曉得你的正數倒數是硬體功能還是用程式碼造成的結果,8bit cpu宣告16bit變數,又擺在中斷裡,出問題的機會很大,要看你的寫法,再來mcu compiler翻錯的可能性是有的,再來compiler最佳化算錯機會還滿大的,沒必要就關掉吧,我還碰過某大廠compiler的函式是錯的,不只浮點運算錯誤,連32bit加法模擬都是錯的,所以程式裡的"ver++"的結果都不對。

cpu的運作模式是不是熟悉?用ICE,把asm/c混合模式打開,仔細觀察每一行組合語言造成記憶體、暫存器、周邊暫存器等等的變化,這個方法幾乎可以找到所有的問題。

當然還有很多可能,很難表達出來,可能要自己找了。