为什么这三种方式在C代码中有所不同?

时间:2011-02-28 10:36:07

标签: 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;
}

3 个答案:

答案 0 :(得分:9)

使用root1,您已声明了节点的本地实例,它将在堆栈中。你没有初始化它,所以它将包含垃圾。

使用root2,您已声明了一个全局实例。默认启动代码将清除全局占用的内存。

使用root,它将存在于堆上,并将包含垃圾。无论占用的内存是否包含0,都是纯粹的运气。如果你使用calloc而不是malloc,它将为你清除内存。

答案 1 :(得分: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? */

这是在堆栈上分配并保持未初始化。再一次,我们无法保证你留下的价值,所以你会发现这会失败。

答案 2 :(得分:0)

分配新节点时,默认情况下其子节点不为NULL。他们得到垃圾值 此外,如果在包含assert.h时,断言宏被禁用,则已定义名为NDEBUG的宏。这允许编码器在调试程序时在源代码中包含许多断言调用,然后通过简单地包括如下行来禁用生产版本的所有调用:

#define NDEBUG

在其代码的开头,包含assert.h之前。

例如:

#undef NDEBUG  
#include <assert.h>