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