2011-02-28 16 views
4

我有這個代碼的一些問題。注意評論。爲什麼?爲什麼這三種方式在C代碼中有所不同?

struct node 
{ 
    struct node *left; 
    struct node *right; 
    int value; 
}; 

static struct node root2; 

int main() 
{  
    struct node *root = (struct node *) malloc(sizeof(struct node)); 

    assert(root->left == NULL); /* not failed. Why? */ 
    assert(root->right == NULL); /* not failed. Why? */ 

    assert(root2.left == NULL); /* not failed. Why? */ 
    assert(root2.right == NULL); /* not failed. Why? */ 

    struct node root1; 
    assert(root1.left == NULL); /* this failed. Why? */ 
    assert(root1.right == NULL); /* this failed. Why? */ 

    free(root); 

    return 0; 
} 

回答

9

在root1中,您聲明瞭一個節點的本地實例,它將在堆棧中。你不初始化它,所以它會包含垃圾。

有了root2,你已經聲明瞭一個全局實例。默認啓動代碼將清除全局佔用的內存。

有了根,它會存在於堆上,並且會包含垃圾。內存佔用是否包含0是純粹的運氣。如果您使用calloc而不是malloc,它將爲您清除內存。

+0

標準需要用'root2'所有'0'進行初始化,我從來沒有聽說過編譯器不會這麼做。 – 2011-02-28 10:56:24

+3

適用於root和root1。 root2應該在符合實現(6.7.8/10)中初始化。 – AProgrammer 2011-02-28 10:56:57

+0

感謝您的澄清,夥計們。將編輯。 – Dave 2011-02-28 11:18:00

0

當你分配一個新節點時,默認情況下它的子不是NULL。他們得到垃圾值。
另外,如果在包含assert.h的時候斷開宏,則名稱爲NDEBUG的宏已被定義。這允許編碼器包含在源代碼中的許多斷言調用在調試程序,然後通過簡單地包括一條線,如禁止生產版本的所有的人:在其代碼的開頭

#define NDEBUG 

,前包含assert.h。

例如:

#undef NDEBUG 
#include <assert.h> 
4

情況1:

struct node *root = (struct node *) malloc(sizeof(struct node)); 
assert(root->left == NULL); /* not failed. Why? */ 
assert(root->right == NULL); /* not failed. Why? */ 

這是一個吸蟲和一般會失敗。無法保證堆中的malloced內存將被清零 - 您需要calloc。也就是說,我見過的許多調試運行時庫都將分配內存爲零,因此我可以相信這適用於調試模式。這在調試和發佈模式之間可能有所不同。

案例2:

static struct node root2; 

全局變量默認爲零。我認爲這是保證行爲,所以這是正確的。

案例3:

struct node root1; 
assert(root1.left == NULL); /* this failed. Why? */ 
assert(root1.right == NULL); /* this failed. Why? */ 

這是在棧中分配和未初始化留下。再次不能保證你留在這裏的價值,所以你會期望這會失敗。

相關問題