[C++] memset 和sizeof 的使用注意


因為使用C++寫小題目時經常需要清除數組,這里記錄下Memset函數的sizeof運算符的使用注意。

 

memset的特點是:將給定地址后連續的內存(包括給定地址),逐個byte初始化為參數中指明的值。

因為是逐byte初始化,所以memset一般只用來清空(賦值為0)

如果不賦值為0,結果是什么呢?假設對於int A[],如果使用memset(A, 1, sizeof(A)),那么數組A的每一個值會被初始化為0x01010101

正因為如此,一般只會出現 memset(A, 0, sizeof(A))

對於堆區分配的數組,int *A = new int[N], memset(A, 0, sizeof(A[0])*N) 也可以達到效果,但要注意,這里第三個參數不能使用sizeof(A),而要指明byte數。

要想知道原因,需要知道sizeof 運算符的作用。它返回的是“占用的棧空間字節數”。如果數組用int A[N]的形式申明,那么sizeof(A)返回的是整個A數組的占用byte數。如果用int *A = new int[N],sizeof(A)返回的依舊是一個int *所占用的byte數,也就是說,32位編譯器會返回 4,64位編譯器會返回8。需要注意的是,對於兩種編譯器,sizeof作用在int *才會有區別,而sizeof(int) 或者 sizeof(a)  (a是一個申明為int的參數) 在兩種編譯器上都返回4。

下面是一個測試程序。編譯環境為gcc 4.8.2 64-bit

    int *B;
    int b;
    cout << "sizeof B: " << sizeof(B) << endl;  //8,因為我的編譯器是64-bit
    cout << "sizeof b: " << sizeof(b) << endl; //4,無論32-bit還是64-bit編譯器,int所占字節數都是4

    B = new int[5];
    B[4] = 7;
    B[3] = 6;
    B[2] = 5;
    B[1] = 3;
    B[0] = 1;

    cout << "-------B---------\n";
    for(i = 0; i < 5; ++i) cout << B[i] << ' '; //1 3 5 6 7
    cout << endl;
    memset(B, 0, sizeof(B));
    for(i = 0; i < 5; ++i) cout << B[i] << ' '; // 0 0 5 6 7 因為B 占了8字節,所以前8 byte置0
    cout << endl;

    int C[3];
    C[2] = 6;
    C[1] = 4;
    C[0] = 2;
    cout << "\n--------C--------\n";
    cout << "size of C: " << sizeof(C) << endl; //12,返回數組所占用的字節數
    for(i = 0; i < 3; ++i) cout << C[i] << ' '; //2 4 6
    cout << endl;
    memset(C, 0, sizeof(C));
    for(i = 0; i < 3; ++i) cout << C[i] << ' '; //0 0 0
    cout << endl; 

 

知道了上面的原理,我們來看看二維數組的初始化。

int A[2][3] 對於這樣的定義方式,我們依然可以通過memset(A, 0, sizeof(A))來完成對整個二維數組的初始化,因為這種方式申明的二維數組本質上還是一維排列。

如果是int **A,然后動態申明一個2*3的二維數組呢?我們可以像上面一樣,通過 memset(A, 0, sizeof(A[0][0])*2*3) 來完成二維數組的初始化嗎?

答案自然是不行。

動態分配的一維數組之所以依然能用Memset(雖然第三參數要指明byte數)來完成賦值,因為在堆區,一維數組的成員依然是連續排列。

而動態分配的二維數組中的int成員在堆區還是連續排列的嗎?當然不是,既然不是,memset就不能得到想要的結果了。那實際結果是啥?memset會清空存放二級指針的連續內存,附帶清除些別的內存區域。之后只要訪問諸如A[0][1]之類的都會引發內存錯誤,因為二維數組的結構已經被破壞。

 

高維數組在初始化時的注意類似於二維數組,這里就不再贅述了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM