Usage wise difference between const & volatile qua

2020-02-26 13:20发布

问题:

I have already gone through the answer of question @ What are the differences between const and volatile pointer in C? I understand the explanation that:

The const modifier means that this code cannot change the value of the variable, but that does not mean that the value cannot be changed by means outside this code. However, volatile says "this data might be changed by someone else" and so the compiler will not make any assumptions about that data.

Which implies that both type of variables can be changed by external event.

But,then where is the difference in usage of const & volatile?

In C, does compiler optimizations work for const?

回答1:

volatile and const are different in many ways, they are two distinctively different features.

Declaring a variable just as const never means "I expect this variable to be modified outside the program", I'm not sure where you got that idea from. If you expect a const variable to be modified outside the code, it must be declared as volatile const or the compiler may assume that the variable is never changed.

By default, plain const variables are just like any kind of variable, they simply can't be modified by the program itself.

Just as for plain variables, const variable behavior depends a lot on in which scope they are declared. Most often they are declared at file scope and then they behave as other variables with static storage duration, except they are (likely) saved at a different part of the memory. If they are declared at local scope, they may change from time to time when the function where they reside is called.

So there are plenty of cases where const variables may be optimized. One common optimization is "string pools", where the compiler checks if the same constant string literal appears twice in the code, and then uses the same address for them. Had you expected such strings to be changed from an external source, but didn't declare them as volatile, you'd get strange bugs.

As for volatile variables, they may be modified by external sources, but they may also be modified by the program, unlike const variables.



回答2:

Objects with const-qualified type are objects like other objects that you may declare in your program, only that you don't have the right to modify them. The underlying object may change for example by aliasing and the compiler has to take care, as for all other objects if such events could have happend. For example

void toto(double const* pi, double* x) {
  printf("%g %g\n", *pi, *x);
  printf("%g %g\n", *pi, *x);
  *x = 5.0;
  printf("%g %g\n", *pi, *x);
}

Here it is perfectly ok to call toto with something like toto(&a, &a) and so inside the function pi and x point to the same memory. For the second printf the compiler can assume since it did no store in the mean time that the values of *pi and *x have not changed. But for the third printf it cannot foresee if *pi has changed so it has to reload the value from memory.

volatile is different from that.

void tutu(double volatile* pi, double* x) {
  printf("%g %g\n", *pi, *x);
  printf("%g %g\n", *pi, *x);
}

Here, for the second printf as before the compiler can assume that *x hasn't changed, but for *pi it must assume that it could have and must reload it from memory. Use cases for volatile are much rarer in daily programmers life, they mainly concern objects that

  • might represent some hardware address
  • that could change in an interrupt handler
  • under some setjmp/longjmp mechanism
  • or by a different thread


回答3:

'const' tells the compiler that the value is never changed, not by the program and not by someone else. When something is const, the compiler will optimize the code accordingly, and will usually replace the variable with constants in code. So even if it changes outside, the program may never know.

'volatile', on the contrary tells the compiler that the variable can be changed from the outside anytime, and then the compiler will not perform such optimizations, as putting the var in a register, but will always read it from memory, in case it changed.



回答4:

Example for demonstrating const

  function1()
  {
      int i = 10;
      function2(&i);
  }
 function2(int const *ptr) // usage of const
 {
      *ptr = 20; //will cause error; outside function can't be modify the value of i
 }

Example for volatile

 function1()
 {
       while(1)
       {
             i = 20;

              print(i);
       }
 }

 function2()
 {
       i = 20;
       while(1)
       {
              print(i);
       }
 }

consider these two function. both are seem to be same. for optimisation compiler convert function1 to function2. problem is that if value of i changed by another thread then two function become different, here while loop print value of i and another module change the value of i. so we will not get the value of i as 20 always.

volatile is used to inform the compiler not to optimise the variable.



回答5:

The const modifier means that this code cannot change the value of the variable, but that does not mean that the value cannot be changed by means outside this code.

There are two different ways to apply the const qualifier.

A const-qualified object must not be modified by the program or the program has undefined behavior. A const volatile object can be modified by the OS/hardware/whatever, but not assigned to by the program. For the avoidance of doubt, a const object is one whose definition uses a const type for it.

A pointer-to-const-qualified-type prevents (at compile time) modifications via that pointer, but other pointers to the same object can be used to modify it. Behavior is defined provided the object itself is not const. However, the compiler may still assume that only the program modifies the object, accounting for arbitrary modifications by the OS/hardware/whatever require volatile.

A pointer-to-non-const-qualified-type is exactly the same as the pointer-to-const as far as modifications via other pointers are concerned.

However, volatile says "this data might be changed by something other than code in this program" and so the compiler will not make any assumptions about that data when optimizing.

So the differences are these:

#include <stdio.h>
void some_other_function(const int *);

int main() {
    int a = 0;
    int volatile b = 0;
    int const c = 0;
    int const *constptr = &a;
    int *ptr = (int*) constptr;

    printf("%d\n", a); // compiler can assume a == 0 at this point, and 
                       // replace the code with puts("0") if it wants to
    printf("%d\n", b); // compiler cannot assume a value for b, it's volatile[*]
    some_other_function(constptr); // defined in another TU
    printf("%d\n", a); // compiler can *no longer* assume that a == 0, 
                       // it might have changed
    *ptr = 1;          // there's another example of a changing, legally
    some_other_function(&c);
    printf("%d\n", c); // compiler can assume c == 0 because c is const
}

[*] Although I say it "can't assume a value", it may be that some hypothetical C implementation happens to know that there is no OS or hardware mechanism to modify an automatic variable by any means that would require volatile to detect. Especially in this case, where no reference to b has escaped the function. If so, then you might find that the implementation actually can ignore volatile in this particular code, but maybe it treats extern global volatile variables "properly" because it knows that the linker provides a means to map them to the addresses of I/O ports or whatever.



回答6:

The difference between Volatile and Const can be easily see in bellow case,

1) If you say some variable as Const, it may not be possible to modify by your program.

2) if you say volatile, it is just giving a hint to the compiler not to optimize the code, because the value may be changed from the external threads or other programs.

3) if we define a variable as Const Volatile, that means this variable can not be modified by same program, will not be optimized by compiler and can be modified by external threads or programs.

example:

if i write a function like below,

const freq = 10;
calfreq()
{
return (Const freq * 2);
}

here in this case compiler may optimize the code to

return(20);

all the time.

But here in m y case, freq value may change, because of external hardware / threads / programs So, if i say Const Volatile, then problem will be fixed.



标签: c volatile