summaryrefslogtreecommitdiff
path: root/devdocs/c/language%2Fvolatile.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
committerCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
commit754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch)
treef1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/c/language%2Fvolatile.html
new repository
Diffstat (limited to 'devdocs/c/language%2Fvolatile.html')
-rw-r--r--devdocs/c/language%2Fvolatile.html86
1 files changed, 86 insertions, 0 deletions
diff --git a/devdocs/c/language%2Fvolatile.html b/devdocs/c/language%2Fvolatile.html
new file mode 100644
index 00000000..fa12c267
--- /dev/null
+++ b/devdocs/c/language%2Fvolatile.html
@@ -0,0 +1,86 @@
+ <h1 id="firstHeading" class="firstHeading">volatile type qualifier</h1> <p>Each individual type in the C <a href="type" title="c/language/type">type system</a> has several <i>qualified</i> versions of that type, corresponding to one, two, or all three of the <a href="const" title="c/language/const"><code>const</code></a>, <code>volatile</code>, and, for pointers to object types, <a href="restrict" title="c/language/restrict"><code>restrict</code></a> qualifiers. This page describes the effects of the <code>volatile</code> qualifier.</p>
+<p>Every access (both read and write) made through an lvalue expression of volatile-qualified type is considered an observable side effect for the purpose of optimization and is evaluated strictly according to the rules of the abstract machine (that is, all writes are completed at some time before the next sequence point). This means that within a single thread of execution, a volatile access cannot be optimized out or reordered relative to another visible side effect that is separated by a <a href="eval_order" title="c/language/eval order">sequence point</a> from the volatile access.</p>
+<p>A cast of a non-volatile value to a volatile type has no effect. To access a non-volatile object using volatile semantics, its address must be cast to a pointer-to-volatile and then the access must be made through that pointer.</p>
+<p>Any attempt to read or write to an object whose type is volatile-qualified through a non-volatile lvalue results in undefined behavior:</p>
+<div class="c source-c"><pre data-language="c">volatile int n = 1; // object of volatile-qualified type
+int* p = (int*)&amp;n;
+int val = *p; // undefined behavior</pre></div> <p>A member of a volatile-qualified structure or union type acquires the qualification of the type it belongs to (both when accessed using the <code>.</code> operator or the <code>-&gt;</code> operator):</p>
+<div class="c source-c"><pre data-language="c">struct s { int i; const int ci; } s;
+// the type of s.i is int, the type of s.ci is const int
+volatile struct s vs;
+// the types of vs.i and vs.ci are volatile int and const volatile int</pre></div> <table class="t-rev-begin"> <tr class="t-rev t-until-c23">
+<td> <p>If an array type is declared with the volatile type qualifier (through the use of <a href="typedef" title="c/language/typedef"><code>typedef</code></a>), the array type is not volatile-qualified, but its element type is.</p>
+</td> <td><span class="t-mark-rev t-until-c23">(until C23)</span></td>
+</tr> <tr class="t-rev t-since-c23">
+<td> <p>An array type and its element type are always considered to be identically volatile-qualified.</p>
+</td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
+</tr> </table> <div class="c source-c"><pre data-language="c">typedef int A[2][3];
+volatile A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of volatile int
+int* pi = a[0]; // Error: a[0] has type volatile int*
+void *unqual_ptr = a; // OK until C23; error since C23
+// Notes: clang applies the rule in C++/C23 even in C89-C17 modes</pre></div> <p>If a function type is declared with the volatile type qualified (through the use of <a href="typedef" title="c/language/typedef"><code>typedef</code></a>), the behavior is undefined.</p>
+<table class="t-rev-begin"> <tr class="t-rev t-since-c99">
+<td> <p>In a function declaration, the keyword <code>volatile</code> may appear inside the square brackets that are used to declare an array type of a function parameter. It qualifies the pointer type to which the array type is transformed.</p>
+<p>The following two declarations declare the same function:</p>
+<div class="c source-c"><pre data-language="c">void f(double x[volatile], const double y[volatile]);
+void f(double * volatile x, const double * volatile y);</pre></div> </td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td>
+</tr> </table> <p>A pointer to a non-volatile type can be implicitly converted to a pointer to the volatile-qualified version of the same or <a href="compatible_type" title="c/language/compatible type" class="mw-redirect">compatible</a> type. The reverse conversion requires a cast expression.</p>
+<div class="c source-c"><pre data-language="c">int* p = 0;
+volatile int* vp = p; // OK: adds qualifiers (int to volatile int)
+p = vp; // Error: discards qualifiers (volatile int to int)
+p = (int*)vp; // OK: cast</pre></div> <p>Note that pointer to pointer to <code>T</code> is not convertible to pointer to pointer to <code>volatile T</code>; for two types to be compatible, their qualifications must be identical:</p>
+<div class="c source-c"><pre data-language="c">char *p = 0;
+volatile char **vpp = &amp;p; // Error: char* and volatile char* are not compatible types
+char * volatile *pvp = &amp;p; // OK, adds qualifiers (char* to char*volatile)</pre></div> <h3 id="Uses_of_volatile"> Uses of volatile</h3> <div class="t-li1">
+<span class="t-li">1)</span> <a href="static_storage_duration" title="c/language/static storage duration"><code>static</code></a> <code>volatile</code> objects model memory-mapped I/O ports, and <code>static</code> <code>const</code> <code>volatile</code> objects model memory-mapped input ports, such as a real-time clock: <div class="c source-c"><pre data-language="c">volatile short *ttyport = (volatile short*)TTYPORT_ADDR;
+for(int i = 0; i &lt; N; ++i)
+ *ttyport = a[i]; // *ttyport is an lvalue of type volatile short</pre></div>
+</div> <div class="t-li1">
+<span class="t-li">2)</span> <code>static</code> <code>volatile</code> objects of type <code><a href="../program/sig_atomic_t" title="c/program/sig atomic t">sig_atomic_t</a></code> are used for communication with <code><a href="../program/signal" title="c/program/signal">signal</a></code> handlers.</div> <div class="t-li1">
+<span class="t-li">3)</span> <code>volatile</code> variables that are local to a function that contains an invocation of the <code><a href="../program/setjmp" title="c/program/setjmp">setjmp</a></code> macro are the only local variables guaranteed to retain their values after <code><a href="../program/longjmp" title="c/program/longjmp">longjmp</a></code> returns.</div> <div class="t-li1">
+<span class="t-li">4)</span> In addition, volatile variables can be used to disable certain forms of optimization, e.g. to disable dead store elimination or constant folding for micro-benchmarks.</div> <p>Note that volatile variables are not suitable for communication between threads; they do not offer atomicity, synchronization, or memory ordering. A read from a volatile variable that is modified by another thread without synchronization or concurrent modification from two unsynchronized threads is undefined behavior due to a data race.</p>
+<h3 id="Keywords"> Keywords</h3> <p><a href="https://en.cppreference.com/w/cpp/keyword/volatile" title="cpp/keyword/volatile"><code>volatile</code></a></p>
+<h3 id="Example"> Example</h3> <div class="t-example">
+<p>demonstrates the use of volatile to disable optimizations</p>
+<div class="c source-c"><pre data-language="c">#include &lt;stdio.h&gt;
+#include &lt;time.h&gt;
+
+int main(void)
+{
+ clock_t t = clock();
+ double d = 0.0;
+ for (int n = 0; n &lt; 10000; ++n)
+ for (int m = 0; m &lt; 10000; ++m)
+ d += d * n * m; // reads from and writes to a non-volatile
+ printf("Modified a non-volatile variable 100m times. "
+ "Time used: %.2f seconds\n",
+ (double)(clock() - t)/CLOCKS_PER_SEC);
+
+ t = clock();
+ volatile double vd = 0.0;
+ for (int n = 0; n &lt; 10000; ++n)
+ for (int m = 0; m &lt; 10000; ++m) {
+ double prod = vd * n * m; // reads from a volatile
+ vd += prod; // reads from and writes to a volatile
+ }
+ printf("Modified a volatile variable 100m times. "
+ "Time used: %.2f seconds\n",
+ (double)(clock() - t)/CLOCKS_PER_SEC);
+}</pre></div> <p>Possible output:</p>
+<div class="text source-text"><pre data-language="c">Modified a non-volatile variable 100m times. Time used: 0.00 seconds
+Modified a volatile variable 100m times. Time used: 0.79 seconds</pre></div> </div> <h3 id="References"> References</h3> <ul>
+<li> C17 standard (ISO/IEC 9899:2018): </li>
+<ul><li> 6.7.3 Type qualifiers (p: 87-90) </li></ul>
+<li> C11 standard (ISO/IEC 9899:2011): </li>
+<ul><li> 6.7.3 Type qualifiers (p: 121-123) </li></ul>
+<li> C99 standard (ISO/IEC 9899:1999): </li>
+<ul><li> 6.7.3 Type qualifiers (p: 108-110) </li></ul>
+<li> C89/C90 standard (ISO/IEC 9899:1990): </li>
+<ul><li> 6.5.3 Type qualifiers </li></ul>
+</ul> <h3 id="See_also"> See also</h3> <table class="t-dsc-begin"> <tr class="t-dsc"> <td colspan="2"> <span><a href="https://en.cppreference.com/w/cpp/language/cv" title="cpp/language/cv">C++ documentation</a></span> for <span class=""><span>cv (<code>const</code> and <code>volatile</code>) type qualifiers</span></span> </td>
+</tr> </table> <div class="_attribution">
+ <p class="_attribution-p">
+ &copy; cppreference.com<br>Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.<br>
+ <a href="https://en.cppreference.com/w/c/language/volatile" class="_attribution-link">https://en.cppreference.com/w/c/language/volatile</a>
+ </p>
+</div>