3

I'm new to C so I know what a pointer is but I'm not convenient with the topic yet.

#include "stdio.h"
#include "stdint.h"
int *value(void) {
    int i=3;
    return &i;
} 

void valueTwo(void) {
    int x=35;
}

main() {
    int *ip;
    ip=value();
    printf("*ip is %d\n", *ip);
    valueTwo();
    printf("*ip==%d\n",*ip);
}

The above code prints *ip is 3 *ip is 35

What I do not understand is why *ip has changed from 3 to 35. From what I understand, this means the value at the address &i has been changed from 3 to 35. However, I don't understand how 35 got into that address. Can anyone explain? Thanks!

Alan H
  • 77
  • 1
  • 7

5 Answers5

3

You are returning address of local variable i that causes undefined behavior according to C standards, the problem is scope and life of local variable is within the function vaule() once control returns access to that variable via address is invalid memory instruction.

edit: If you compile your code with -Wall then it will also give you warning:

$ gcc -Wall  -pedantic x.c
x.c: In function ‘value’:
x.c:5:5: warning: function returns address of local variable 
[enabled by default]

suppose your code name is x.c

You can rectify your code with dynamic memory allocation as follows:

int *value(void) {
    int* i = malloc(sizeof(*i));  // it is dynamically allocated memory 
    *i = 3; // assigned 3 at allocated memory 
    return i; // safely return its address 
} 

Now, *i in main is safe because life of dynamically allocated memory is till program executes.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
3

What you are seeing is undefined behavior.

int *value(void) {
    int i=3;
    return &i;
}

As soon as the function finishes, int i goes out of scope. The pointer thus is invalid. Everything happening after that is undefined.

dornhege
  • 1,500
  • 8
  • 8
2

When i is assigned in the function value, it's allocated on the stack -- that is, it's a temporary location set up just for the time that value is running. When it exits, you've passed back a pointer to it, but it's no longer technically valid. It'll still work, if you're lucky, because nothing's overwritten that area of memory yet.

When you call the second function, it is allocated exactly the same way as the first one, and so it happens to put that first variable "x" in exactly the same spot on the stack where the "i" was before. You can't rely on this happening -- another compiler might show different behavior. But that's why it's writing 35 over the spot where "i" used to be.

This is a good exercise for understanding how the compiler works, but don't do this in a real program. Only set pointers to point to things whose allocations are going to stick around as long as needed.

Chris Bogart
  • 472
  • 2
  • 8
  • Thanks to everyone who answered so quickly. The code was from lecture slides, and was an example of something that shouldn't be done but I didn't quite understand why 35 takes over later. Now it's clear to me. I apologize for tagging both c and c++. I have edited my question. – Alan H Apr 19 '14 at 18:38
  • @AlanH I notice new users post better explanation comparatively. – Grijesh Chauhan Apr 19 '14 at 18:39
  • 1
    @GrijeshChauhan Your answer helped me a lot in a sense of how it should be done correctly. I guess Chris gave me more step by step explanations as to why it's wrong. I only wish it would let me pick multiple answers :( – Alan H Apr 19 '14 at 18:47
  • 1
    @AlanH yes that why I edited my comment (in grace period) and change 'answer' to 'explanation' I would also select Chris's answer. – Grijesh Chauhan Apr 19 '14 at 18:49
1

This code

int *value(void) {
    int i=3;
    return &i;
}

The int i is on the stack. Return the address but when the function ends this part of the stack is free to be used by others.

I.e. Do not do this as demonstrated

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
1

Returning the address of a local variable is a disaster. Where do you suppose the 'i' local variable is stored? Answer: The exact same place the 'x' local variable is stored.

ScottMcP-MVP
  • 10,337
  • 2
  • 15
  • 15