#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;


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. 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

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.