Say I have a struct
typedef struct A{
int a1;
int *a2;
}A_t;
Now if I declare an instance of this struct to be volatile -
volatile A_t trial;
And I use a volatile pointer to access this volatile struct.
volatile A_t *ptrToTrial = &trial;
If I try to do this:
int *ptrToField = ptrToTrial->a2;
Should ptrToField
be volatile as well? Would the compiler know that prtToField
is volatile without explicit mention because it is accessed through ptrToTrial
which is volatile?
Also if there is a function -
function trialFunction(A_t *trialptr)
{
int *p = trialptr->a2;
}
If we call this function with the volatile ptr declared above -
trailFunction(ptrToTrial)
I get an error: volatile A_t* is incompatible with parameter of type A_t
.
So if I change the function definition to include volatile
, I do not see an error.
function trialFunction(volatile A_t *trialptr)
{
int *p = trialptr->a2;
}
Shouldn't the compiler also complain about the pointer p
- because p
is non-volatile and trialptr->a2
is volatile?
Should
ptrToField
be volatile as well?
With your definition of struct A
, the thing pointed to by member a2
is not declared to be volatile
. That a given instance of struct A
is volatile
implies that its member a2
(the pointer) is volatile
, but not that the thing it points to is volatile
. This is the difference between int * volatile
(equivalent to the actual case) and volatile int *
.
The initialization you describe ...
int *ptrToField = ptrToTrial->a2;
... initializes ptrToField
with the value of pointer ptrToTrial->a2
. Because ptrToTrial
points to a volatile
object, the program must load the pointer (a member of that volatile object) from main memory. Because the thing pointed to is not (declared to be) volatile, however, no information is lost and no (new) risk is inherent in declaring the type of ptrToField
's target as a plain int
. Certainly there is no advantage in declaring ptrToField
itself as volatile.
Do also note, in case it is unclear, that the name of your variable ptrToField
is inconsistent with the use to which you put it. You do not initialize it to point to a member of your struct
; rather, you initialize it as a copy of a member of your struct
.
Would the compiler know that
prtToField
is volatile without explicit mention because it is accessed throughptrToTrial
which is volatile?
It is not required to exercise any such knowledge it might have, and that knowledge in any case would be likely to be very limited in scope. It knows how that variable was initialized, but it may be difficult to predict when and how its value might thereafter be modified. In any case, any information not carried by the declared type of the variable is not relevant to the standard C semantics of your program.
Shouldn't the compiler also complain about the pointer p - because p is non-volatile and trialptr->a2 is volatile?
No, because although trialptr->a2
is volatile, there is no problem with reading its value (at some given point in time) and assigning that value to another variable. Object values are bit patterns, they are neither volatile nor non-volatile -- that's a characteristic of their storage, as communicated via the lvalues by which they are accessed.
Please be noted that int *a2;
in your struct A
is not volatile.
So
int *ptrToField = ptrToTrial->a2;
ptrToField
is not volatile
.
trailFunction(ptrToTrial)
gets error because the function trailFunction
expects A_t *trialptr
, but you pass volatile A_t*
, it's obviously compile error.
And finally:
function trialFunction(volatile A_t *trialptr)
{
int *p = trialptr->a2;
}
It's OK to compile, because a2
's type is int*
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With