By the declaration
const int i;
it is clear that i cannot be modified.
Then why does the declaration   
void f (const int *p) 
is modifying p? ( I tested it, it is modifying p but don't know how?). 
By the declaration
const int i;
it is clear that i cannot be modified.
Then why does the declaration   
void f (const int *p) 
is modifying p? ( I tested it, it is modifying p but don't know how?). 
 
    
    The placement of const in a pointer declaration matters. You read it backwards:
const int *p means "p is a pointer to int which is constant"int * const p means "p is a constant pointer to int"const int * const p means "p is a constant pointer to a constant int" 
    
    Because const is int pointed to by p, not p -- the pointer to the int.
const int *p
means that p is a pointer to const int, p can be modified, *p not.
The same way
int *const p
means that p cannot be modified, whereas *p can.
Note that const int* p is the same as int const* p.
The simple rule is that the declaration reads from right to the left: int const *p means "p is a pointer to constant int", int *const p means "p is a constant pointer to an int".
(The actual complete rule is more complicated, you can use http://cdecl.org/ for "decoding" C-style declarations.)
 
    
    because in this expression, p is a pointer to a const int. Which means you can change what p points to.
This also means that, "p" can itself be modified, but the contents of "p" cannot be modified, so *p = 10; will yield error.
An example will clear things:
#include <stdio.h>
void foo(const int *p)
{
  int x = 10;
  p = &x; //legally OK
  //  *p = 20; <- Results in an error, cannot assign to a read-only location. 
  printf("%d\n",*p);
}
int main(int argc, char *argv[])
{
  const int x10 = 100;
  foo(&x10);
  return 0;
}
To make the above program not modify the pointer at all:
#include <stdio.h>
void foo(const int *const p)
{
  int x = 10;
  p = &x; //legally NOT OK, ERROR!
  //  *p = 20; <- Results in an error, cannot assign to a read-only location. 
  printf("%d\n",*p);
}
int main(int argc, char *argv[])
{
  const int x10 = 100;
  foo(&x10);
  return 0;
}
