1

I am wondering how efficient / is working the volatile declaration. In the following code:

volatile char var1 = * (volatile char *) 0x2000000;
printf("%d \n", var1 + 1);

It means that every time I am using the variable "var", it will be loaded from the address memory 0x2000000, but is the volatile cast of a fixed address necessary, or is it only to fit the type of var1?

Does this means that every time "var1" is read, it is read from memory, and not from a potential cached value? So in this code, we access two times the address 0x2000000?

Jone
  • 13
  • 2
  • 2
    volatile means just that. It tells the compiler that it can assume nothing about the location and that it must reload each time. Useful for I/O mapped registers (for example) where the compiler has no idea on what is actually there. – Michael Dorgan Feb 28 '18 at 22:53
  • But the cast should be unnecessary in my opinion – Jone Feb 28 '18 at 22:54
  • 1
    The volatile on `var1` seems not needed. Generally the pointer as volatile is enough for my example. – Michael Dorgan Feb 28 '18 at 22:55
  • If worried, look at the assembly output. It will tell all... – Michael Dorgan Feb 28 '18 at 22:56
  • 1
    You're mistaken about the declaration, though. You've declared a variable var1 *on the stack*, and initialized it from 0x2000000. But subsequent reads of that variable will come from its stack address. – Lee Daniel Crocker Feb 28 '18 at 22:56
  • Curious if that `var1` on stack would reload the stack value each time instead of placing it into a register. That would be interesting and not what seems intended from the original code where it seems they want the address lookup each time... – Michael Dorgan Feb 28 '18 at 22:58

2 Answers2

2

but is the volatile cast of a fixed address necessary, (?)

Yes, consider the below. Compiler could reason (char *) 0x2000000 was read once, no need to read again for volatile char var2 = * (char *) 0x2000000;. Just use the value that was read before and saved away in some internal memory/register. Targets var1/var2, being volatile, do not affect the right-hand-side of the assignment.

volatile char var1 = * (char *) 0x2000000;
printf("%d \n", var1);
volatile char var2 = * (char *) 0x2000000;
printf("%d \n", var2);

The volatile with volatile char var1 is not needed. Defining a pointer to volatile data is likely more in line with coding goals.

volatile char *ptr1 = (volatile char *) 0x2000000;
printf("%d \n", *ptr1);
printf("%d \n", *ptr1);  // A 2nd read of `(volatile char *) 0x2000000` occurs.
chux - Reinstate Monica
  • 127,356
  • 13
  • 118
  • 231
  • 1
    Ok I think I got it, you mean (and the others people commenting too) that the "volatile char var1" implies that I will read the value from the stack every time I read "var1". The value cached is dropped. But the real value is stored only once on the stack, so the value fetched by "var1" is only valable once. – Jone Feb 28 '18 at 23:23
  • @Jone Not quite. `volatile char var1 = 5; printf("%d \n", var1); printf("%d \n", var1); printf("%d \n", var1);` would require code to read `var1` 3-times and not optimize code to do `printf("5\n5\n5\n");`. But this has nothing to do with volatile data pointed to by `(volatile char *) 0x2000000`. – chux - Reinstate Monica Feb 28 '18 at 23:31
1

As you have written it, volatile char var1 = * (volatile char *) 0x2000000;, this says to create an object named var1 (allocated at a place the C implementation chooses) and to initialize it to a value read from 0x2000000. Every time var1 is read, the copied value will be read from the place the implementation allocated. It will not be reread from 0x2000000.

You may want volatile char *var1 = (volatile char *) 0x2000000;. This defines var1 to be a pointer to 0x2000000. With this definition, every time *var1 is used, the value will be read from 0x2000000.

Eric Postpischil
  • 168,892
  • 12
  • 149
  • 276