[Edit: OK, so this question is more subtle than I thought at the beginning.]
Declaring a pointer to a constant or a reference to const never helps the compiler to optimize anything. (Although see the Update at the bottom of this answer.)
A const declaration only indicates how the identifier will be used within its declaration; he does not say that the main object cannot change.
Example:
int foo(const int *p) { int x = *p; bar(x); x = *p; return x; }
The compiler cannot assume that *p not changed by calling bar() , since p can be (for example) a pointer to a global int and bar() can change it.
If the compiler knows enough about the calling element foo() , and the contents of bar() , which can prove that bar() does not change *p , then it can also perform this proof without declaring const.
But this is true in general. Since const only affects the scope of the declaration, the compiler can already see how you handle the pointer or link in that scope; he already knows that you are not modifying the base object.
In short, all const in this context do not allow you to make mistakes. It does not tell the compiler anything that it does not know yet, and therefore it has nothing to do with optimization.
What about functions calling foo() ? How:
int x = 37; foo(&x); printf("%d\n", x);
Can the compiler prove that this prints 37, since foo() accepts const int * ?
No. Even if foo() accepts a pointer to const, it can discard const-ness and change int. (This is not undefined behavior.) Here again, the compiler cannot make any assumptions at all; and if he knows enough about foo() to do such an optimization, he will know that even without const .
The only time const can allow optimization is the following cases:
const int x = 37; foo(&x); printf("%d\n", x);
Here, to change x to any mechanism (for example, by pointing to it and discarding const ), undefined Behavior is called. Therefore, the compiler may assume that you are not doing this, and it may propagate the constant 37 to printf (). Such an optimization is legal for any object that you declare const . (In practice, a local variable to which you will never accept a link will not be useful, because the compiler can already see if you are changing it in your area.)
To answer the question "side note", (a) the const pointer is a pointer; and (b) the const pointer may be NULL. You are right that the internal representation (i.e. Address) is most likely the same thing.
[update]
As Christoph points out in the comments, my answer is incomplete because it does not mention restrict .
Section 6.7.3.1 (4) of the C99 standard states:
During each execution of B, let L be any l-value that has & L based on P. If L is used to access the value of the object X that it denotes, and X is also modified (in any way), then the following requirements apply: T should not be const-qualified ....
(Here, B is the base unit over which P, a delimiter-pointer-to-T, is in the region.)
So, if the function C foo() declared as follows:
foo(const int * restrict p)
... then the compiler may assume that no changes to *p occur during the lifetime of p - that is, during the execution of foo() - because otherwise the Behavior will be Undefined.
So, in principle, combining restrict with a pointer to a constant can allow both optimizations that were fired above. I wonder if any compilers really implement such an optimization? (GCC 4.5.2, at least not.)
Note that restrict exists only in C, not C ++ (even C ++ 0x), except as an extension to the compiler.