Is It Safe to Cast Away volatile?
Nothing. If you don't access the volatile memory, the semantics of volatile are unaffected. If you accessed volatile memory through a casted non-volatile pointer, the compiler might optimize the reference away. If the value had changed, you'd have the wrong value. For some value of wrong. ;-)
The delete doesn't access the volatile memory, it just frees it. Sort of an uncommon thing to do with volatile memory.
Can you cast away volatile on a member from a volatile function
Yes. To cast away the volatile-ness of an object, const_cast
is used:
T & t = const_cast<T&>(volatile_t);
This is the way. But whether you should use it in your code or not, I cannot say without looking at the code. In general, casting away the const-ness as well as volatile-ness, is a dangerous idea, and should be done only after very careful examination of all cases.
How to cast away the volatile-ness?
Use const_cast
.
For example,
volatile sample *pvs = new sample();
sample *ps = const_cast<sample*>(pvs); //casting away the volatile-ness
That is, const_cast
is used to cast away both const-ness as well as volatile-ness. Unfortunately, its name doesn't contain the term "volatile". Maybe, that is because the keyword const
is more common in use than the keyword volatile
. As one of the comment says, cv_cast
would have been more appropriate name!
Cast away volatile in plain old C
It's a bit tricky but you can get the preprocessor to help you here, if you only want to convert from pointer types to pointer types.
#define cv_cast(TYPE,expr) (*((TYPE)(expr)) = *(expr),(TYPE)(expr))
Usage:
typedef struct {
float f;
} Foo;
typedef struct {
char b;
} Bar;
void somefunction(void) {
Foo f; Bar b;
Foo volatile* foov = &f;
Foo* foo = 0;
Bar* bar = &b;
foo = cv_cast(Foo*,foov); // legal (no error, no warning)
foov = cv_cast(Foo*,foo); // legal (no error, no warning)
foo = cv_cast(Foo*,bar); // illegal (an error)
}
The basic trick here is that we force an assignment from Bar
to Foo
in a cv_cast
from Bar*
to Foo*
. This is done in the part after the ,
. It will trigger an error if and only if you are casting incompatible pointer types.
However, note that cv_cast
ing pointers that point to invalid locations (e.g. NULL
) will cause segfaults.
Note: For reference (in the comments) this post used a helper function nullfn
previously that is not necessary. You can look it up in the history if you're interested.
When can a volatile variable be optimized away completely?
Writes to volatile variables (even automatic ones) count as observable behaviour.
C11 (N1570) 5.1.2.3/6:
The least requirements on a conforming implementation are:
— Accesses to volatile objects are evaluated strictly according to the rules of the abstract
machine.— At program termination, all data written into files shall be identical to the result that
execution of the program according to the abstract semantics would have produced.— The input and output dynamics of interactive devices shall take place as specified in
7.21.3. The intent of these requirements is that unbuffered or line-buffered output
appear as soon as possible, to ensure that prompting messages actually appear prior to
a program waiting for input.This is the observable behavior of the program.
The question is: does initialization (e
, f
) count as an "access"? As pointed out by Sander de Dycker, 6.7.3 says:
What constitutes an access to an object that has volatile-qualified type is implementation-defined.
which means it's up to the compiler whether or not e
and f
can be optimized away - but this must be documented!
C26492 Don't use `const_cast` to cast away const or volatile (type.3)
The cleanest way, I believe, would be to use GetBuffer.
At some point you will find a function that really needs non-const string :)
Casting volatile variable in c
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
.
Should I qualify pointer parameters with volatile if they may be changed during the execution of a function?
volatile
was intended for things like memory-mapped device registers, where the pointed-to value could "magically" change "behind the compiler's back" due to the nature of the hardware involved. Assuming you're not writing code that deals with special hardware that might "spontaneously" change the value that bar
points to, then you needn't (and shouldn't) use the volatile
keyword. Simply omitting the const
keyword is sufficient to let the compiler (and any programmer that might call the function) know that the pointed-to value is subject to change.
Note that if you are intending to set *bar
from another thread, then the volatile
keyword isn't good enough; even if you tag the pointer volatile, the compiler still won't guarantee correct handling. For that use-case to work correctly, you need to either synchronize all reads and writes to *bar
with a mutex, or alternatively use a std::atomic<int>
instead of a plain int
.
Related Topics
When to Return a Pointer, Scalar and Reference in C++
How to Print the Address of Char Array
When Does a Std::Vector Reallocate Its Memory Array
What Happen to Pointers When Vectors Need More Memory and Realocate Memory
Is Using an Union in Place of a Cast Well Defined
Special Characters in Visual Studio 2019 C++ Project and Executing Cmd Commands with Them
How to Make Sure That Std::Random_Shuffle Always Produces a Different Result
Test If Stdin Has Input for C++ (Windows And/Or Linux)
Rodrigues into Eulerangles and Vice Versa
Access to Method Pointer to Protected Method
Partially Truncating a Stream (Fstream or Ofstream) in C++
Why Is This Simd Multiplication Not Faster Than Non-Simd Multiplication
Strange Behavior with Constexpr Static Member Variable
Programmatically Check Whether My MAChine Has Internet Access or Not
Create 2D Array Using Size from Parameters in C++