views:

482

answers:

2

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.

+4  A: 

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.

Robert Gould
http://www.netrino.com/node/80 Seems to support that idea. I've never read up on volitile. Good stuff.
Kieveli
"volatile aren't too useful": don't know about PC software, but in embedded systems, they're essential for declaring hardware registers or variables that can be changed in interrupts.
Steve Melnikoff
Very good point! It's been a few years since my last embedded project, so I forgot that. Anyways that worked because it was for loads and stores. On the PC it's easy to forget about most interrupts as they get abstracted away by the OS api.
Robert Gould
+1  A: 

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.

FreeMemory
so couldn't you just dovolatile struct x* volatile foo; for a volatile pointer and struct?
Earlz
@earlz: Yes. Exactly. volatile struct x* volatile foo is a volatile pointer to a volatile struct x.
FreeMemory