Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting volatile variable in c

I think I have a tricky question, but I'm sure you will be able to help me. Let's say I have a function like this:

char my_function (int example);

I use this function in multiple cases, sometimes the argument it receives is a volatile variable and sometimes a non-volatile variable. That cause some warnings when I compile my code that can be easily removed by using casts, but I want to understand which is the safer scenario and why.

Scenario 1:

Prototype: char my_function (int example);

int a;
volatile int b;

my_function (a);  // Everything is fine.
my_function ((int)b);  // Avoided the warning, by casting the variable and            saying it's no longer volatile. 

Scenario 2:

Prototype: char my_function (volatile int example);

int a;
volatile int b;

my_function(b);  // Everything is fine.
my_function((volatile int)a); // Avoided the warning, by casting 'a' saying that now it's volatile.

I understand how volatile modifier works, I mostly use it because I program micro-controllers and I need to ensure that some of my variables are never optimized out when they are hardware modified. I am a bit confused about casting the volatile modifier and that is why I want to understand which is the safer scenario apart from just removing the warning.

like image 435
cventu Avatar asked Aug 16 '16 17:08

cventu


2 Answers

It really depends on what my_function does with its argument.

Remember that volatile prevents certain optimizations - predominantly it forces the variable to be re-read every time it is referenced. Thus this code

volatile int a;
int b;
// ...
b = a + 1;
b = a + 2;

will read a for each statement and, as a may have changed values between them, give the correct result.

When you pass a volatile into a function as a parameter, you only get one read of the variable. This may then be used multiple times within the function (effectively losing the volatile nature).

Remember that C is pass-by-value. When you invoke the function as

my_function((int)b); // b is declared volatile

The compiler generates code to read b once in the calling code, and push the value it read onto the stack (usually), then invoke my_function. This copy is then referenced within my_function as example, and no matter how often you reference example you will always get the same value (even if the original b variable has since changed many times).

That might be exactly what you want - take a snapshot of the variable and do several computations on its value.

If it's not what you want, you need to consider passing in a pointer with the appropriate volatile qualifications.

char my_function( volatile int *example);

And call it thus:

my_function(&a);
my_function(&b);

Then reference *example inside my_function.

like image 177
kdopen Avatar answered Sep 23 '22 17:09

kdopen


The cast doesn't actually do anything. In the call my_function (b); the code reads the volatile int b. That's where the "volatile" matters, during the read. The result of the read is already an int and not a volatile int. There are no volatile int values. Even if there were volatile int values, passing it to my_function would convert it to plain int, just as the cast does.

It may be that the compiler assumes that passing a volatile int variable to a function is something dangerous worth a warning, and by adding a cast to int you indicate that you know what you are doing.

like image 37
gnasher729 Avatar answered Sep 25 '22 17:09

gnasher729