1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
<h1 id="firstHeading" class="firstHeading">const 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 <code>const</code>, <a href="volatile" title="c/language/volatile"><code>volatile</code></a>, 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>const</code> qualifier.</p>
<p>Objects <a href="declarations" title="c/language/declarations">declared</a> with const-qualified types may be placed in read-only memory by the compiler, and if the address of a const object is never taken in a program, it may not be stored at all.</p>
<p>Any attempt to modify an object whose type is const-qualified results in undefined behavior.</p>
<div class="c source-c"><pre data-language="c">const int n = 1; // object of const-qualified type
int* p = (int*)&n;
*p = 2; // undefined behavior</pre></div> <p><code>const</code> semantics apply to <a href="value_category" title="c/language/value category">lvalue</a> expressions only; whenever a const lvalue expression is used in context that does not require an lvalue, its <code>const</code> qualifier is lost (note that volatile qualifier, if present, isn't lost).</p>
<p>The lvalue expressions that designate objects of const-qualified type and the lvalue expressions that designate objects of struct or union type with at least one member of const-qualified type (including members of recursively contained aggregates or unions), are not <i>modifiable lvalues</i>. In particular, they are not assignable:</p>
<div class="c source-c"><pre data-language="c">const int n = 1; // object of const type
n = 2; // error: the type of n is const-qualified
int x = 2; // object of unqualified type
const int* p = &x;
*p = 3; // error: the type of the lvalue *p is const-qualified
struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
s1 = s2; // error: the type of s1 is unqualified, but it has a const member</pre></div> <p>A member of a const-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>-></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
const struct s cs;
// the types of cs.i and cs.ci are both const 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 const type qualifier (through the use of <a href="typedef" title="c/language/typedef">typedef</a>), the array type is not const-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 const-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];
const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const int
int* pi = a[0]; // Error: a[0] has type const 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 const type qualifier (through the use of <a href="typedef" title="c/language/typedef">typedef</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>const</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[const], const double y[const]);
void f(double * const x, const double * const y);</pre></div> </td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td>
</tr> </table> <table class="t-rev-begin"> <tr class="t-rev t-since-c99">
<td> <p>const-qualified compound literals do not necessarily designate distinct objects; they may share storage with other compound literals and with string literals that happen to have the same or overlapping representation.</p>
<div class="c source-c"><pre data-language="c">const int* p1 = (const int[]){1, 2, 3};
const int* p2 = (const int[]){2, 3, 4}; // the value of p2 may equal p1+1
_Bool b = "foobar" + 3 == (const char[]){"bar"}; // the value of b may be 1</pre></div> </td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td>
</tr> </table> <p>A pointer to a non-const type can be implicitly converted to a pointer to const-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;
const int* cp = p; // OK: adds qualifiers (int to const int)
p = cp; // Error: discards qualifiers (const int to int)
p = (int*)cp; // OK: cast</pre></div> <p>Note that pointer to pointer to <code>T</code> is not convertible to pointer to pointer to <code>const 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;
const char **cpp = &p; // Error: char* and const char* are not compatible types
char * const *pcp = &p; // OK, adds qualifiers (char* to char*const)</pre></div> <h3 id="Keywords"> Keywords</h3> <p><a href="https://en.cppreference.com/w/cpp/keyword/const" title="cpp/keyword/const"><code>const</code></a></p>
<h3 id="Notes"> Notes</h3> <p>C adopted the <i>const</i> qualifier from C++, but unlike in C++, expressions of const-qualified type in C are not <a href="constant_expression" title="c/language/constant expression">constant expressions</a>; they may not be used as <a href="switch" title="c/language/switch">case</a> labels or to initialize <a href="static_storage_duration" title="c/language/static storage duration">static</a> and <a href="thread_storage_duration" title="c/language/thread storage duration">thread</a> storage duration objects, <a href="enum" title="c/language/enum">enumerators</a>, or <a href="bit_field" title="c/language/bit field">bit-field</a> sizes. When they are used as <a href="array" title="c/language/array">array</a> sizes, the resulting arrays are VLAs.</p>
<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">
© cppreference.com<br>Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.<br>
<a href="https://en.cppreference.com/w/c/language/const" class="_attribution-link">https://en.cppreference.com/w/c/language/const</a>
</p>
</div>
|