關於memset

這個題目好像重覆又重覆,但我最近發現了一些有趣的東西,想和大家分享一下,順便當作温故知新吧。(已是給一些從未用過memset的作一個簡單的introduction)

int a[10];
for (int i=0; i<10; i++)
    a[i]=0;

利用memset,這段code便可簡化成︰

#include<cstring>

int a[10];
memset(a,0,sizeof(a));

如果很多array要initialize,memset便使整段code更為簡潔,更加易明了。

可是,很多coder非常容易誤用memset,好像下面這段code︰

int a[10];
for (int i=0; i<10; i++)
    a[i]=1;

該如何簡化呢?

int a[10];
memset(a,1,sizeof(a));

很可惜,這是錯的。整個a[]會變成16843009,絶對不是你想要的東西吧。應該如何寫呢?

答案是memset並不可以這樣做。要知道原因,請繼續看下去 :-P

memset的原意是對character的array做整體的改變,例子可看 https://www.cplusplus.com/reference/clibrary/cstring/memset/
而memset的好處是這樣做會比用for loop逐個改快。

一個character佔1 byte,所以memset幫string裏面每一個character的1 byte都改變,成為你想要assign的character。可是一個integer是4 byte,如果我們只指定一個byte的值給它,它唯有(強行)改變它的用法,變成一個重覆4次的byte。

從以上例子可看到,(0) 10 =(00000000) 2 ,而(1) 10 =(00000001) 2 ,因此memset的結果分別是(00000000 00000000 00000000 00000000) 2 和(00000001 00000001 00000001 00000001) 2 ,在十進制分別為0和16843009。

這樣看來,memset的用處不大,但實際program的時候,我至少找到4個用處(4個常用的value)。

(1)
int a[10];
memset(a,0,sizeof(a));
得出的值是0。

(2)
int a[10];
memset(a,-1,sizeof(a));
得出的值是-1。

(3)
int a[10];
memset(a,127,sizeof(a));
得出的值是大約是+infinity。

(4)
int a[10];
memset(a,128,sizeof(a));
得出的值是大約是-infinity。

原理和上面講述的一模一樣。但更強的是,連long long都可以用同樣數值來initialize一個array,應用範圍更廣。

所以,以後要做shortest path,做BFS,做其他要initialize的program時,memset將會是你省時,省code length的好幫手。