Warning[...]: undefined behavior: the order of volatile accesses is undefined in this statement x.cpp xxx
Why this line is undefined behavior?
case 2:
Vdda = 3.3 * (*VREFINT_CAL) / ADC_DR->DATA;
Where the declarations/initializations are:
volatile short const *VREFINT_CAL = (short *) 0x1FFFF7BA;
and
volatile STRUCT_ADC_DR *ADC_DR = (STRUCT_ADC_DR*) 0x40012440;
defined by:
typedef struct
{
unsigned DATA : 16;
unsigned : 16;
} STRUCT_ADC_DR;
Is it because the compiler isn't sure about the volatile elements could act diferent in the order they get accessed? (What is the case)
But shouldn't it be ensured that the calculation gets performed from left to right as the operators have the same priority?
In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres.
When we run a code, sometimes we see absurd results instead of expected output. So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.
In computing (particularly, in programming), undefined value is a condition where an expression does not have a correct value, although it is syntactically correct. An undefined value must not be confused with empty string, Boolean "false" or other "empty" (but defined) values.
Undefined Behavior results in unpredicted behavior of the entire program. But in unspecified behavior, the program makes choice at a particular junction and continue as usual like originally function executes.
volatile
implies to the compiler that you are reading something that is not an ordinary memory address, like an I/O port. For two such reads, it is very likely that you will want those reads to happen in a certain order.
In both C and C++, the evaluation order of operands is not defined. If it helps you, think of the division as a function call:
Vdda = 3.3 * divide(*VREFINT_CAL, ADC_DR->DATA);
The point is now, that for volatile
, where it's likely that the order is important, you might not want to leave this decision to the compiler. So it warns about it.
To get rid of the warning, simply make the order explicit by introducing additional sequence points to your code. For instance:
short const x = *VREFINT_CAL;
unsigned const y = ADC_DR->DATA;
Vdda = 3.3 * x / y;
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