Search code examples
ccastingvolatile

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.


Solution

  • 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.