-7
  1. why does the pointer "a" points to the correct location when i call the function for the second time

  2. because during the second function call to "cr" the statements in the if block will not be executed so how the hell does the pointer "a" remember its previous location even though its not a static variable

code:

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

typedef struct heavy{
    int data;
    struct heavy *nxt;
}ode;

void cr(ode**);
void prin(ode*);

int main()
{
    ode*head=NULL;
    cr(&head);cr(&head);
    prin(head);
    getch();
    return 0;
}

void cr(ode**p)
{
    ode*temp,*a;
    temp=*p;

    if(temp==NULL)
    {
        a=(ode*)malloc(sizeof(ode));
        a->data=1;
        a->nxt=(ode*)malloc(sizeof(ode));
        *p=a;
        a=a->nxt;
        a->nxt=NULL;
    }else{
        a->data=2;
        a->nxt=NULL;
    }
}

void prin(ode*head)
{
    if(head==NULL)
        printf("list is empty");
    while(head!=NULL)
    {
        printf("%d",head->data);
        head=head->nxt;
    }
}
ozzy
  • 1
  • 3
  • 1
    Really, this is your best Question? -> `why is this code working ` – Michi Sep 13 '17 at 17:03
  • 1
    Explicitly unremembering would waste CPU cycles. Don't rely on undefined behaviour. – Bathsheba Sep 13 '17 at 17:05
  • Please ___properly___ indent your code. Machine (Compiler) can read and compile anything, but for humans, it needs to make a little _sense_ while reading a block of text as _code_. – Sourav Ghosh Sep 13 '17 at 17:06
  • [Please see this discussion on why not to cast the return value of malloc() and family in C..](https://stackoverflow.com/q/605845/2173917) – Sourav Ghosh Sep 13 '17 at 17:06
  • It is preferred if you can post separate questions instead of combining your questions into one. That way, it helps the people answering your question and also others hunting for at least one of your questions. Thanks! – Sourav Ghosh Sep 13 '17 at 17:07
  • 1
    in `void cr(ode**p)` you should check `a` because is used uninitialized. -->> `a->data=2;`. What happens if `temp != NULL` ? – Michi Sep 13 '17 at 17:08

1 Answers1

0

When you don't assign any value to a local variable (in this case we're talking about a) the program will behave in an unpredictable way, thus we say undefined behavior. This means that your program work correctly just by chance, and you should always remember to assign values before using the variables.

In particular, in this case I can guess why it's working every time you run it, and it has to do with how function calls work in C. Let me explain.

When we make a call to a function, a new frame (layer) in the stack (a place in memory where local variables and other "local-ish" things are stored). As you can expect from what I just said, a stack is organized in layers. Let me expose an example.

If in a particular function called George() I declare and use 2 local variables

int George(){
    int a;
    int b;
    a = 5;
    return 0;
}

the compiler will know that space for 2 variables is needed, so when I call the function it will reserve space for those 2 local variables to be stored. The new stack frame will be something like:

| 'a': ____ | <-- 4 bytes space for variable a
| 'b': ____ | <-- 4 bytes space for variable b
|-----------|

(While keeping in mind that this is not a realistic representation of the stack, it's good enough to explain what's going on)

Those spaces reserved for the values of the variables are NOT set to a default value, they contain what there was in memory before (and right now we can't make any guess).

When I call this function from another function (i.e. main) a stack frame with that shape will be added (push) to the stack:

int main(){
    int hello = 7;
    int hey;
    hey = George(); // Here we make the function call
    return 0;
}

The stack will then be something like:

STACK:
    | 'a': ____    | <- 'George' stack frame, containing
    | 'b': ____    |    local variables of George
    |--------------|
    | 'hello': 7   | <- 'main' stack frame, containing
    | 'hey': ____  |    local variables of main
    |--------------|

After the 3rd line of George, just before the return, the stack will be:

 STACK:
      | 'a': 5       | <- Variable a has been set to 5
      | 'b': ____    |    
      |--------------|
      | 'hello': 7   | 
      | 'hey': ____  |   
      |--------------|

and then there will be a return. Here, the stack is pop'd, which means a frame is deleted (we are returning in the main function "domain", so we discard local variables of George).

STACK:
    | 'hello': 7   | <- 'main' stack frame, with hey replaced with
    | 'hey': 0     |    George return value (0)
    |--------------|

And everything works fine, BUT the memory we pop'd just right now is not set to 0 or some other default value. It stays like that until some other program overrides it. Which means that, while we are not using those values anymore, they're probably still there.

In this state, if we call George another time, we will have our stack pushed another time:

 STACK:
      | 'a': ____    | <- 'a' address is in the same position
      | 'b': ____    |    where there was the 'a' in the previous
      |--------------|    function call to Giorgio
      | 'hello': 7   | 
      | 'hey': ____  |   
      |--------------|

In this state, if we don't assign any value to a it will (probably) contain the value that the a had on the previous function call, because the 'new' a has the same address of the 'previous' a, because the function called is the same and there was no other function call in between that could override the previous value. If we do so, before we assign any value to the new local variable a, it contains 5.

The same happens to your program when you run

cr(&head);
cr(&head);

twice, one before the other. The value of your local variable a is probably kept unchanged.

Anyway, explanation apart, NEVER use this kind of behaviors in your code. This is a very very bad way of programming, and the outcome is usually unpredictable.

I hope my explanation was not too bad.