Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why these three ways are different in C code?

Tags:

c

I have some problem with this code. Notice the comments. Why that?

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;
}
like image 394
HiMing Avatar asked Dec 12 '22 15:12

HiMing


2 Answers

With root1, you've declared a local instance of a node, and it will be on the stack. You don't initialise it, so it will contain garbage.

With root2, you've declared a global instance. The default startup code will clear the memory that globals occupy.

With root, it will exist on the heap, and will contain garbage. It is pure luck whether the memory occupied contains 0 or not. If you use calloc instead of malloc, it will clear the memory for you.

like image 74
Dave Avatar answered Dec 15 '22 06:12

Dave


Case 1:

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

This is a fluke and will generally fail. There's no guarantee that malloced memory from the heap will be zeroed - you need to calloc for that. That said, many debug runtime libraries I have seen will zero allocated memory so I can believe this works for you in debug mode. This may vary between debug and release modes.

Case 2:

static struct node root2;

Global variables are zeroed by default. I think this is guaranteed behaviour so this is correct.

Case 3:

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

This is allocated on the stack and left uninitialised. Again there's no guarantee about the values you're left with here so you would expect this to fail.

like image 31
Rup Avatar answered Dec 15 '22 04:12

Rup