The volatile
keyword was designed to be applied to objects that represent storage and not to functions. Returning a volatile int
from a function does not make much sense. The return value of a function will not be optimized away (with the possible exception of inlined functions, but that's another case altogether...), and no external actor will be modifying it. When a function returns, it passes a copy of the return value to the calling function. A copy of a volatile
object is not itself volatile
. Therefore, attempting to return a volatile int
will result in a copy, casting it down to a non-volatile int
, which is what is triggering your compiler messages. Returning a volatile int*
might be useful, but not a volatile int
.
Passing an object by value into a function makes a copy of the object, thus using a volatile int
as a function parameter necessarily involves a conversion that ignores a qualifier. Passing a volatile by address is perfectly reasonable, but not by value.
According to the C spec, the behavior of volatile
is completely implementation-dependent, so YMMV.
Are you using volatile
in this way to try to defeat some sort of compiler optimization? If so, there is probably a better way to do it.
Edit:
Taking into account the updates to your question, it appears that you may be able to approach this in a different way. If you are trying to defeat compiler optimizations, why not take the direct approach and simply tell the compiler not to optimize some things? You can use #pragma GCC optimize
or __attribute__((optimize))
to give specific optimization parameters for a function. For example, __attribute__((optimize(0)))
should disable all optimizations for a given function. That way, you can keep your data types non-volatile and avoid the type problems you are having. If disabling all optimizations is a bit too much, you can also turn individual optimization options on or off with that attribute/pragma.
Edit:
I was able to compile the following code without any warnings or errors:
static int functionTwo(int *number) {
return *number + 1;
}
typedef union {
int i;
volatile int v;
} fancy_int;
int main(void) {
fancy_int count;
count.v = 10;
count.v = functionTwo(&count.i);
return 0;
}
This hack"technique" probably has some kind of odd side-effects, so test it thoroughly before production use. It's most likely no different that directly casting the address to a (int*)
, but it doesn't trigger any warnings.