#include <stdio.h>

int *check();

int main()
{
    int *c;
    c = check();
    printf("%d\n", c);
    return 0;
}

int *check()
{

   int  i=10; int *p=&i;    
     return p;

}

Dani AI

Generated

Short answer: the program has undefined behavior, so seeing "10" is just an accident of one particular run/implementation and not meaningful.

There are two independent problems here. First, as already noted, the function returns the address of a local (automatic) variable; that object ceases to exist when the function returns, so the pointer becomes indeterminate. Second, the call uses printf("%d", c) where %d expects an int but you pass an int *. Variadic functions like printf do no type checking or conversion for mismatched arguments, so that mismatch itself is undefined behavior. 's citation of the standard backs up the lifetime/type rules; 's question about dereferencing is understandable, but you don't need to explicitly write *c to run into UB — using the indeterminate pointer or passing it with the wrong format is enough.

Because the behavior is undefined, many outcomes are possible. On one run the stack slot that used to hold 10 may still contain that value, or the compiler/register behavior may produce the decimal 10 when the wrong type is interpreted — or the program could crash or print a large garbage number on another system. You cannot rely on any observed result.

Safer alternatives (pick one):

/* return the integer by value */
int get_value(void) { return 10; }

/* or return address of static storage */
int *get_static(void) { static int v = 10; return &v; }

/* or allocate on the heap (remember to free) */
int *get_heap(void) { int *p = malloc(sizeof *p); *p = 10; return p; }

Also: always match printf format specifiers (%d for int, %p for pointer with (void*)), compile with warnings (-Wall -Wextra -Wformat) and use runtime tools (-fsanitize=undefined, Valgrind) to catch these bugs.

Recommended Answers

All 8 Replies

why the o/p is 10.

It's not.

The code has undefined behavior because check() is returning a pointer to an object that doesn't exist after check() returns to it's caller. That is illegal in C and C++.

Since the pointer is never actually dereferenced, is it really undefined behavior?

yes -- printf() will attempt to use it.

I did not know that merely using (without dereferencing) a pointer already invoked undefined behavior. Learn something new every day.

it's undefined because you have no idea what other functions will do with it. It also easily allows bugs into the program.

it's undefined because you have no idea what other functions will do with it.

Admittedly I just found out that it's undefined 45 minutes ago, but I'm pretty sure that's not the reason why. By that logic copying the pointer to a different variable or passing it to a function that we defined ourselves would not invoke UB because then we would know what's being done with it. But according to this (page 49, lines 14+) any use of an illegal pointer invokes UB.

Also we do know what printf does with its arguments. Since the standard does not mandate that the argument for %d shall be a pointer that's legal to dereference (which it doesn't, since the argument for %d shouldn't even be a pointer), any implementation that does dereference the argument would be in violation of the standard. Likewise the standard does not mandate that %p (which the OP should be using) dereferences its argument and therefore it won't. In particular it is legal to do printf("%p", arr+n) where arr is an array of size n. If printf could potentially dereference an argument for %p, that would not be legal.

As a sidenote, there's another reason why the code invokes undefined behavior: %d expects an integer, but is given a pointer.

Relevant fragements from the C(99) specification (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf):

6.2.4 Storage durations of objects
-----------------------------------

The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address,25) and retains
its last-stored value throughout its lifetime.26) If an object is referred to outside of its
lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.


6.3.2.3 Pointers (Point 6)
--------------------------

Any pointer type may be converted to an integer type. Except as previously specified, the
result is implementation-defined. If the result cannot be represented in the integer type,
the behavior is undefined. The result need not be in the range of values of any integer
type.


7.1.4 Use of library functions
-------------------------------

Each of the following statements applies unless explicitly stated otherwise in the detailed
descriptions that follow: If an argument to a function has an invalid value (such as a value
outside the domain of the function, or a pointer outside the address space of the program,
or a null pointer, orapointer to non-modifiable storage when the corresponding
parameter is not const-qualified) or a type (after promotion) not expected by a function
with variable number of arguments, the behavior is undefined.
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.