and I get this warning 2, wherever I call functionTwo with a COUNT pointer argument instead of an int pointer

[Warning] cast discards qualifiers
from pointer target type

obviously variables/pointers can't be "cast" to volatile/un-volatile.. but every arguments must be specified as volatile too? so how can I use any library function if it's already defined for non-volatile variable?

I hope this is an academic question. If it is a real problem you are trying to solve, the approach you selected might be taking you down a difficult path. I can't think of a good reason why you'd want to pass a volatile into a function by value.
–
AmardeepJul 21 '10 at 20:50

@Amardeep I can't either find any reason, but if I don't do that way, I get second warning telling me I should specify volatile in prototype for volatile variables
–
Hernán EcheJul 22 '10 at 13:03

5 Answers
5

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:

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.

+1 it's an option, I will try to solve it with optimization, following Jukka Suomela answer, it's needed to make a copy of the object, but I think I should be enough with a cast, for sure gcc makers have a reason to give the warning anyway
–
Hernán EcheJul 22 '10 at 16:27

It's possible that I am way off base here but volatile isn't something normally associated with stack memory region. Therefore I'm not sure if the following prototype really makes much sense.

volatile int functionOne(volatile int number);

I'm not sure how a returned integer can be volatile. What's going to cause the value of EAX to change? The same applies to the integer. Once the value is pushed onto the stack so that it can be passed as a parameter what's going to change its value?

I think nothing will!, but then if I define the function like functionTwo (without volatile inside argument) I get the warningTwo every time I call with a volatile variable if that isn't specified in the prototype..
–
Hernán EcheJul 21 '10 at 20:59

As I understand it, it's not a question of whether something can change a stack variable. Declaring a stack variable as volatile forces the compiler to always read / write the value from / to the stack location instead of optimizing the code by caching that stack location's contents in a register.
–
PraetorianJul 21 '10 at 21:55

Note that any access to a volatile variable is "special". In the first version with functionTwo(COUNT *number), functionTwo knows how to access it properly. In the second version with countcopy, the main function knows how to access it properly when assigning countcopy = copy.

Argument of functionTwo is "int *number", and not "COUNT *number", change that and then you'll get the warnings (Imagine you are dealing with an already common library function that gets *int as argument) but the vars of your code are volatile (+1 for the try and the example)
–
Hernán EcheJul 22 '10 at 12:05

it's ok for an int, but if you have an array, it's not memory efficient to make a copy just to avoid a warning
–
Hernán EcheJul 22 '10 at 13:02

It's not about "avoiding warnings", it's about correctness. :) With an explicit copy, you will have the right semantics (whatever it happens to mean in your implementation), and you know exactly where you have read or write accesses to volatile objects. If you just take a pointer, discard the "volatile" qualifier, and pass it to a library function, all bets are off (undefined behaviour).
–
Jukka SuomelaJul 22 '10 at 13:19

you are right that's about to know when you read/write volatile objects. so remains to be seen if there is some other way, because if there is not other way, in the case of an array, it's a memory waste
–
Hernán EcheJul 22 '10 at 13:30

It's possible that those who wrote it wanted to be sure that all the operations are atomic, and declared all int variables as volatile (is it a MT application with poor syncronization?), so all the ints from the code are declared as volatile "for consistency".

Or maybe by declaring the function type as volatile they expect to stop the optimizations of the repeated calls for pure functions? An increment of a static variable inside the function would solve it.
However, try to guess their original intention, because this just does not make any sense.

@Alexandre you might be wrong, if you do var = var + 1 and var is not volatile, then it can be change in the midle of the operation inside an interruption service routine (for embedded) or a thread, and then if the compiler don't read real var updated value, the operation that could be var = var(Updated) + 1, will lose atomicity doing var = var(NoUpdated) + 1, and the updated value will be lost
–
Hernán EcheJul 22 '10 at 13:45