一:函式宣告:void *memset(void *s, int c, size_t n);
memset:將s所指向的某一塊記憶體中的每個位元組的內容全部設定為ch指定的ASCII值,
塊的大小由第三個參數指定,這個函數通常為新申請的記憶體做初始化工作, 其傳回值為指向S的指標。
1.1:普通理解
大家平時用的最多的就是對一個數組進行初始化。
例如
int data[100];
memset(data, 0, sizeof(data));
函數目的就是將data數組所有元素初始化為0. 有人經常把第三個參數寫成:sizeof(int) * 100; 其實也是一樣的。具體原因稍後描述。
1.2:值得糾正和注意的地方
1.樣本:memset(data, 1, sizeof(data))。顯然目的是想將data的所有元素初始化成1,經過實驗,發現不對,記憶體中出現大量的16843009。
不是我們想要的1。
原因剖析,memset函數是以位元組為單位進行賦值的,他經常應用在對一個字串的所有元素賦值。
例如
char data[20];
memset(data, '#', sizeof(data));
而樣本1中的data是整型的,使用 memset還是按位元組賦值,就是對data指向的記憶體的100個位元組進行賦值,每個都用ASCII為1的字元去填充,轉為二進位後,1就是00000001,佔一個位元組。一個INT元素是4 位元組,合一起就是00000001000000010000000100000001,就等於16843009,就完成了對一個INT元素的賦值了。這樣賦值完以後,每個數組元素的值實際上是0x01010101即十進位的16843009。你看看你輸出結果是否這樣?所以大家一定要記住memset是以位元組為單位進行複製的。所以前面提到的關於第三個參數的兩種寫法都是正確的,應為他都是這個數組所佔的位元組個數。所以第三個參數你還可以直接寫成100(對於前面那個例子)。
也能感受到memset用於把整型數組初始化為0,完全是對記憶體比較瞭解或者投機取巧的人弄出來的。我們用的時候一定要小心,要理解其原理。不然就會犯很多錯誤。
總結一下,memset其實是對單個位元組操作的。類似於strset。只是strset只能對字串操作。而memset可針對任何類型。切不可亂用。
二:void *memcpy(void *dest, const void *src, int n);
memcpy: 從源src所指的記憶體位址的起始位置開始拷貝n個位元組到目標dest所指的記憶體位址的起始位置中。注意事項:
1.source和destin所指記憶體地區不能重疊,函數返回指向destin的指標。
2.strcpy和memcpy主要有以下3方面的區別。
2.1 複製的內容不同。strcpy只能複製字串,而memcpy可以複製任意內容,例如字元數組、整型、結構體、類等。
2.2 複製的方法不同。strcpy不需要指定長度,它遇到被複製字元的串結束符"\0"才結束,所以容易溢出。memcpy則是根據其第3個參數決定複製的長度。
2.3 用途不同。通常在複製字串時用strcpy,而需要複製其他類型資料時則一般用memcpy
3.如果目標數組destin本身已有資料,執行memcpy()後,將覆蓋原有資料(最多覆蓋n)。如果要追加資料,則每次執行memcpy後,要將目標數組地址增加到你要追加資料的地址。
注意,source和destin都不一定是數組,任意的可讀寫的空間均可,這就是厲害的地方。
三:void *memmove( void* dest, const void* src, size_tcount
);
memmove:由src所指記憶體地區複製count個位元組到dest所指記憶體地區。memmove支援兩端記憶體有重疊部分。因此memmove比memcpy安全。
附memcpy和memmove的原始碼:
void * __cdecl memcpy ( void * dst, const void * src, size_t count ){ void * ret = dst; /* * copy from lower addresses to higher addresses */ while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } return(ret);} void * __cdecl memmove ( void * dst, const void * src, size_t count ){ void * ret = dst; if (dst <= src || (char *)dst >= ((char *)src + count)) { /* * Non-Overlapping Buffers * copy from lower addresses to higher addresses */ while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } } else { /* * Overlapping Buffers * copy from higher addresses to lower addresses */ dst = (char *)dst + count - 1; src = (char *)src + count - 1; while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return(ret);}