How does one create an array of volatile structs? Each struct contains 3 function pointers.
i.e. is it
State_t * volatile states[10];
or
volatile State_t * states[10];
??
Also, should the struct properties be defined as volatile as well?
This is to ensure function pointers are not cleared by compiler. Code works fine when compiled with GCC. However, the second entry in the array returns rubbish compiled with the ARM compiler for Cortex-M3.
State_t *volatile states[10];
The above means states is an array of 10 volatile pointers to objects of type State_t. The volatile keyword here qualifies the pointers, not the value pointed to.
State_t volatile *states[10];
The above means states is an array of 10 pointers to objects of type volatile State_t. Here, the volatile keyword qualifies not the the pointer, but the value pointed to. The above can also be written as
volatile State_t *states[10];
To answer the latter part of your question, if you qualify a structure variable as volatile, then all its members are volatile. However, the volatile qualification is not part of the structure definition.
volatile struct states {
// stuff
} state_a;
struct states state_b;
Here, state_a is volatile qualified but state_b is not. Therefore, you need to qualify each states instance explicitly as volatile unless you create states instances in the same statement as the structure definition.
Related
Clarification about terminology used:
For static array I mean array statically memory allocated like: int x[10].
The problem
I need to declare a static array with volatile elements.
If I well understood how volatile qualifier works, it should be:
volatile uint8_t *x; // x is a pointer to volatile uint8_t
uint8_t *volatile x; // x is a volatile pointer to uint8_t
volatile uint8_t *volatile x; // x is a volatile pointer to volatile uint8_t
Ok, but now I need to do the same thing with a static array.
I tried with:
volatile uint8_t x[10]; // Only the pointer is decleared as volatile
uint8_t volatile x[10]; // Same as above
volatile uint8_t *x3[10]; // Casting problems and errors when I do ...
*x3[0] = 1; // ... something like this. Moreover, I do not know if this...
// ... statement declares the uint8_t element as volatile
Thanks!
UPDATE
Ok, as highlighted in the comments I should use:
volatile uint8_t x[10]
As I could understand, the problem is not in the declaration but in the usage of this variable in my code. I pass this element to a function whose prototype is:
static void functionName(uint8_t *buffer, uint32_t size);
I call the function in this way:
functionName(x, 10);
The compiler reports: passing argument 1 of 'functionName' discards 'volatile' qualifier from pointer target type
I can't change the function prototype, how can I solve the problem?
What you have to do to declare a static array of 10 volatile elements of type uint8_tis just:
volatile uint8_t x[10];
Be aware that this is a declaration of an array, which has nothing to see with pointers at this step.
Note: Later in your code, if you use x, it may decay to a pointer to the first volatile element, but in this case this pointer will have a constant value, given at the linking step. The pointed value is obviously volatile.
Stumbled across the problem myself today.
A variable CAN be 'sometimes' volatile.
Being volatile means, that its value can changed outside the program flow. By a parallel thread or an ISR.
Now if the ISR is what changes the value 'unexpectedly', it won't change unexpectedly inside the ISR itself. So for the ISR, the variable is not volatile and disabling compiler optimizations for it is counterproductive.
If I call a function from inside the ISR (and only from there), then the variable is not volatile and I don't want to pass a pointer to volatile, as it would produce inefficient code.
For this case, the solution I found was to have two declarations:
int a[x] = {};
volatile int * b = a;
Now the outside world uses b (globally declared in the header file) and treats the values pointed to by b as volatile, while the ISR (locally) defines both and uses a, treating the values as being not volatile.
Well, this is a very special case. In general, a function only sees the function parameter declaration. Which is either volatile or not, so the funciton will treat a parameter either always as being volatile or always as being not. It cannot automatically switch between two maybe completely differently compiled code blocks depending on the original volatile qualifier state of the passed parameter. Hence the warning.
Why would one create a volatile pointer? And suppose I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
volatile int *pData;
or
volatile int * volatile pData;
Why would one create a volatile pointer?
Example: To access data whose pointer is updated by a background process.
Stuff * volatile VideoFrame;
for (;;) {
Block_Changes();
Stuff MyCopy = *VideoFrame;
Allow_Changes();
Use(&MyCopy);
}
I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
The 2nd meets the goal. volatile int * volatile pData; is a:
pData as volatile pointer to volatile int
The 1st volatile int *pData; is a non-volatile pointer to volatile data:
pData as pointer to volatile int
The volitle keyword is most often used in this context. # Eugene Sh.
One reason to use the modifier `volatile' is so the compiler does not optimize the variable out of existence.
Another reason to use the modifier 'volatile' is so when ever the code references that variable, it accesses the actual variable and not the value left in some register.
Another reason to use the modifier 'volatile' is when the variable value can change outside the control of the current program. For instance a hardware register or when an 'interrupt' updates the variable that your application is reading.
I vaguely remember that the order of the volatile keyword has influence on wether you want the pointer to the array to be volatile or the contents itself. If I want the content to be volatile, do I need to write:
volatile short Array[];
or
short volatile Array[3];
Either will do. It is the difference between
short volatile * ptr; /* pointer to volatile short */
and
short * volatile ptr; /* volatile pointer to short */
that matters.
const behaves the same way.
Both of them will work fine. Order of specifiers doesn't matter.
Read this answer for more detailed explanation.
volatile void * ptr;
Whether ptr is volatile or it points to the volatile location.
So the actual doubt is :
Is the same thing applied to the above declaration as it applied with const qualifier ?
Little explanation will help me a lot.
It's a pointer to volatile data. If the pointer itself should be volatile but not the data it points at, you'd use:
void * volatile ptr;
So yes, it works the same way as the const modifier.
A Microsoft explanation:
The volatile keyword specifies that the value associated with the name that follows can be modified by actions other than those in the user application.
The volatile keyword is useful for declaring objects in shared memory that can be accessed by multiple processes.
Both const and volatile are type qualifiers (they're the only type qualifiers in C, in fact). The syntax for using them is identical.
I have an issue with some low level code I am writing, I need to use objects as volatile, but it is not necessarily so that I want the types to be declared as volatile (for reusability reasons). I can however define pointer to a qualified variant of a structure as detailed in the following segment.
struct x {
int bar;
};
struct x foobar;
...
volatile struct x *foo = &foobar;
Now foo is effectively a pointer to an object of the type:
volatile struct x {
volatile int x;
};
since volatile apply to all struct members. Now my question is when an object contain a pointer to another object, how is the volatileness applied?
struct x {
struct y *bar;
};
Will a pointer to a volatile instance of x then then treat this as:
volatile struct x {
struct y * volatile bar;
};
or as:
volatile struct x {
volatile struct y * volatile bar;
};
I've read through the C standard, and it is not very clear regarding this, and I can easily interprete the wording in multiple ways.
In your example you
get a volatile pointer, that's all, the volatility isn't extended to the object.
Expanding on my answer volatile is a relaxed atomic, that means access is atomic, but instructions won't be. So you can't threadsafely increment or decrement a volatile, so you can't use a volatile pointer for interation, only store/load (assigment) operations.
Same goes for an int or another number, and volatile also won't work with floats because they are processed in the FPU pipeline, not the CPU. All in all volatile aren't too useful, but Microsoft's compilers automatically place instruction guards around volatiles, making them true atomic values, but that's not part of the standard.
Reading through the standard here, it seems as though the pointer is volatile, but not the actual contents of the struct itself. I interpreted that from the example given, const t * volatile p (at the bottom of the link). The wording, however, is vague, but I think that this would be a similar example:
struct foo {
int bar;
};
struct foo *volatile x;
Note that I have not tried this, so I may be wildly incorrect... it is simply what I've gathered from a cursory read-through of the standard.
Furthermore, cdecl does clear up some of the vagueness. For example:
cdecl> explain volatile struct x* foo
declare foo as pointer to volatile struct x
Whereas:
cdecl> explain struct x* volatile foo
declare foo as volatile pointer to struct x
In one instance, the struct is volatile. In the other, the pointer.