void *memset(void *s, int v, size_t n);
英文釋義如下:
Copies the value v (converted to type unsigned char) to the first n bytes pointed to by s; returns s.
這里s可以是數(shù)組名,也可以是指向某一內(nèi)在空間的指針;v為要填充的值;n為要填充的字節(jié)數(shù),通常為sizeof(s);
使用memset時(shí)要注意的是,memset是逐字節(jié)進(jìn)行填充,所以s一般為char *型。對(duì)于其它類型的s,可以填充的值有兩個(gè),0和-1。這是因?yàn)橛?jì)算機(jī)中用二進(jìn)制補(bǔ)碼表示數(shù)字,0和二進(jìn)制補(bǔ)碼為全0,-1的二進(jìn)制補(bǔ)碼為全1。如果要初始化為其它的值,可以用一個(gè)for循環(huán),如:
for(int i=0;i<n;i++)s[i]=v; memset某個(gè)結(jié)構(gòu)(或其它的數(shù)據(jù)類型)在C語(yǔ)言中是很常見的代碼,其目的是對(duì)結(jié)構(gòu)(或其它的數(shù)據(jù)類型)進(jìn)行初始化,通常都是將變量置為NULL或者0。在C++中,針對(duì)類對(duì)象除了用構(gòu)造函數(shù)初始化對(duì)象外,也可以使用memset來(lái)進(jìn)行初始化操作(確實(shí)有這種情況,不得已而為之,請(qǐng)大家不要把雞蛋砸過(guò)來(lái)!)。但是一定要注意以下所說(shuō)的這種情況:如果類包含虛擬函數(shù),則不能用 memset 來(lái)初始化類對(duì)象。下面是一個(gè)例子:
class GraphicsObject{
protected:
char *m_pcName;
int m_iId;
//etc
public:
virtual void Draw() {}
virtual int Area() {}
char* Name() { return m_pcName;}
};
class Circle: public GraphicsObject{
void Draw() { /*draw something*/ }
int Area() { /*calculate Area*/ }
};
void main()
{
GraphicsObject *obj = new Circle; // 創(chuàng)建對(duì)象
memset((void *)obj,NULL,sizeof(Circle)); // memset to 0
obj->Name(); // 非虛函數(shù)調(diào)用沒問題
obj->Draw(); // 在這里死得很難看
}
結(jié)果我就不說(shuō)了。因?yàn)槊總€(gè)包含虛函數(shù)的類對(duì)象都有一個(gè)指針指向虛函數(shù)表(vtbl)。這個(gè)指針被用于解決運(yùn)行時(shí)以及動(dòng)態(tài)類型強(qiáng)制轉(zhuǎn)換時(shí)虛函數(shù)的調(diào)用問題。該指針是被隱藏的,對(duì)程序員來(lái)說(shuō),這個(gè)指針也是不可存取的。當(dāng)進(jìn)行memset操作時(shí),這個(gè)指針的值也要被overwrite,這樣一來(lái),只要一調(diào)用虛函數(shù),程序便崩潰。這在很多由C轉(zhuǎn)向C++的程序員來(lái)說(shuō),很容易犯這個(gè)錯(cuò)誤,而且這個(gè)錯(cuò)誤很難查。
為了避免這種情況,記住對(duì)于有虛擬函數(shù)的類對(duì)象,決不能使用 memset 來(lái)進(jìn)行初始化操作。而是要用缺省的構(gòu)造函數(shù)或其它的 init 例程來(lái)初始化成員變量。
posted on 2007-12-10 22:56
小果子 閱讀(1907)
評(píng)論(4) 編輯 收藏 引用 所屬分類:
學(xué)習(xí)筆記