Is there any practical difference between the following prototypes?
void f(const int *p);
void f(const int *restrict p);
void f(const int *volatile p);
The presence of a top-level volatile qualifier applied to a parameter in a function's definition may cause behavior to be defined in some cases where it otherwise would not. Most notably:
int test(int volatile x)
{
if (setjmp(&someJumpBuff)) return x;
x++;
someFunction(); // A function that calls longjmp(&someJumpBuff, 1);
x--;
return x;
}
If x were not declared volatile, a compiler could optimize out the x++ and x-- since it could assume that no other code would ever examine the value of x between those two operations. The volatile declaration, however, would force the compiler to presume that code which examines x after the setjmp might execute between the x++ and x-- and thus observe the value x held at that time.
It may be possible to contrive a platform calling convention where a "clever" optimizer that knew nothing about a function's definition beyond the fact that it did not use a volatile qualifier on an argument would be able to generate code that would not be allowable in the presence of such a qualifier, but even on such a platform, a compiler that only saw that a function's prototype lacked a volatile qualifier would have no basis for assuming that its definition wouldn't include one.