Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++: casting away volatile considered harmful?

Tags:

c++

c

volatile

(related to this question Is It Safe to Cast Away volatile?, but not quite the same, as that question relates to a specific instance)

Is there ever a case where casting away volatile is not considered a dangerous practice?

(one particular example: if there is a function declared

void foo(long *pl);

and I have to implement

void bar(volatile long *pl);

with part of my implementation requiring bar() to call foo(pl), then it seems like I can't get this to work as is, because the assumptions made by the compilation of foo() and the compilation of the caller of bar() are incompatible.)


As a corollary, if I have a volatile variable v, and I want to call foo(&v) with someone else's function void foo(long *pl), and that person tells me it's safe, I can just cast the pointer before the call, my instinct is to tell them they're wrong because there's no way to guarantee that, and that they should change the declaration to void foo(volatile long *pl) if they want to support the use of volatile variables. Which one of us is correct?

like image 319
Jason S Avatar asked Sep 09 '11 21:09

Jason S


1 Answers

If the variable is declared volatile then it is undefined behaviour to cast away the volatile, just as it is undefined behaviour to cast away the const from a variable declared const. See Annex J.2 of the C Standard:

The behavior is undefined in the following circumstances:

...

— An attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type (6.7.3).

— An attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type (6.7.3).

If, however, you just have a volatile pointer or a volatile reference to a non-volatile variable then you can freely cast away volatile.

volatile int i=0;
int j=0;

volatile int* pvi=&i; // ok
volatile int* pvj=&j; // ok can take a volatile pointer to a non-volatile object

int* pi=const_cast<int*>(pvi); // Danger Will Robinson! casting away true volatile
int* pj=const_cast<volatile int*>(pvj); // OK
*pi=3; // undefined behaviour, non-volatile access to volatile variable
*pj=3; // OK, j is not volatile
like image 159
Anthony Williams Avatar answered Oct 12 '22 15:10

Anthony Williams