Assigning any value to the variable at the time of declaration is known as initialization while assigning any value to variable not at the time of declaration is known assignment.
If we replace line 1 by "auto int a = 1;" and line 2 by "register int a = 2;", then 'a' becomes non-static in prtFun(). The output of first prtFun() remains same. But, the output of second prtFun() call is changed as a new instance of 'a' is created in second call. So "4 2" is printed again. Finally, the printf() in main will print "2 0". Making 'a' a register variable won't change anything in output.
In above program, compiler treats the three i's as totally different variables, since they are defined in different block. Once the control comes out of the innermost block, the variable i with value 3 is lost, and hence the i in the second printf() refers to i with value 2. Similarly, when the control comes out of the next innermost block, the third printf() refers to the i with value 1. Hence it is clear that scope of of i is local to the block in which it is defined.