LukesDiner
LukesDiner

Reputation: 155

After casting a volatile variable in c, is the variable still volatile?

Let's say that I have a static global variable a, that is cast to an int in a function call during init(). After init(), is a still volatile when used in the function my_function_2?

static volatile int a;

init(void)
{
  my_function_1((int)a);
}

my_function_2(void)
{
/* After init(), is a still volatile? */
}

Does a need to be re-qualified as volatile in my_function_2()? I'm using c99.

Upvotes: 0

Views: 533

Answers (4)

Eric Postpischil
Eric Postpischil

Reputation: 222828

A cast can only convert a value; it cannot affect an object (the memory of a variable). And values do not have qualifiers such as volatile.

When an object’s value is used in an expression, qualifiers are removed, per C 2018 6.3.2.1 2:

Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue;…

So, in (int)a, the a is converted from a volatile int lvalue to an int value before the cast occurs. The cast has no effect; it converts an int to an int. Also note that the value is cast—your title asks about “casting a volatile variable,” but it is impossible to cast a variable, because it is automatically converted to its value before the cast.

So the cast has no effect on a. The object a remains volatile. Its value is passed to my_function_1 as a value without the volatile qualifier.

Upvotes: 1

Devolus
Devolus

Reputation: 22094

The variable a will be volatile for it's entire lifetime. If you cast it to some different type and assign it to a new variable, then this new variable will not be volatile unless you specify it so.

volatile means that the compiler doesn't rely on a previously known value and should not apply appropriate optimizations, so if you cast that away and still reference it , than it is undefined behavior.

Here you don't need to declare b as volatile

volatile int a;

void func(int b)
{
     // This doesn't need to be volatile as it will never be changed from the outside, since it was passed by value.
     printf("%d\n", b);
}

init(void)
{
    // Access a and pass the value to func
    // This is fine, because volatile applies only to access of 'a'.
    func(a);
}

Another example:

void func(volatile int *p)
{
     // 'p' needs to be volatile as it will reference 'a' which is volatile
     printf("%d\n", *p);
}

init(void)
{
    func(&a);
}

Upvotes: 2

Lundin
Lundin

Reputation: 213872

It's undefined behavior to refer to the value through a non-qualified type. If you "cast away" volatile you aren't allowed to access that memory location through a non-volatile qualified type.

C17 6.7.3/6:

If 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, the behavior is undefined

You can however still do a copy of it:

static volatile int a;
int b = a;      // ok, lvalue conversion, drops qualifiers during copy
*(int*)&a = ... // undefined behavior

Upvotes: 1

klutt
klutt

Reputation: 31389

What volatile means is basically that it can be modified externally. This can never change. If you have declared a variable as volatile, then it is volatile.

Upvotes: 1

Related Questions