Q:

Variable undeclared error when used inside a function

Variable 'a' doesn't resolve by pre processor macro when function fun() is defined above main() but working fine when defined below main().
#include <stdio.h>

void fun()
{
    printf("%d",a);
}

int main()
{
    #define a 5
    fun();
    return 0 ;
} 

What is the reason behind it? And how can we make it work so that I don't have to move the function fun() definition.

A:

The C preprocessor runs top-down and replaces the #defines ("text replacement"). So, when #define a 5 in main(), it can't "go back" and replace a in func(); it can only replace the a's, if any, below its #define.
You just need to define it above func().
From C11 draft, 6.10.3 Macro replacement:

A preprocessing directive of the form
# define identifier replacement-list new-line

defines an object-like macro that causes each subsequent instance of
  the macro name 171) to be replaced by the replacement
  list of preprocessing tokens that constitute the remainder of the
  directive. The replacement list is then rescanned for more macro names
  as specified below.

This has been the same since pre standard C. From Dennis Ritchie's C Reference Manual:

12.1 Token replacement A compiler-control line of the form
# define identifier token-string
(note: no trailing semicolon) causes the preprocessor to replace
  subsequent instances of the identifier with the given string of tokens
  (except within compiler control lines). The replacement token-string
  has comments removed from it, and it is surrounded with blanks. No
  rescanning of the replacement string is attempted.

(emphasis mine).

A:

Of course you can't reference a preprocessor macro before defining it, that's simply not how it works.
There's no "variable" here though, your usage of the word is very confusing. The preprocessor is simply doing text replacement, the compiler will never see the a symbol, it will see the 5 instead (if the macro was defined).
I don't know a way to "make it work" since the goal is very strange. If you want to access a global variable, use one:
#include <stdio.h>

int fun(int x)
{
    extern int a;
    return a + x;
}

int a = 12;

int main(void) {
    printf("a=%d, fun() returned %d\n", a, fun(11));
    return 0;
}

Here extern makes us get away with defining a after fun(), but it can't be inside main().

A:

The preprocessor will replace any instances of a with 5 after the point of macro definition. You could place the #define line above the function fun.
As a side note, a is not a variable, the preprocessor will just do a text replacement before it is compiled. It would change fun to
void fun()
{
    printf("%d", 5);
}

