Const (computer programming): Difference between revisions

Content deleted Content added
No edit summary
Tag: Reverted
Because its not useful
Tag: Reverted
Line 2:
{{lowercase title}}
 
== Introduction ==
When applied in an [[object (computer science)|object]] [[Declaration (computer programming)|declaration]],{{efn|Formally when the <code>const</code> is part of the outermost derived type in a declaration; pointers complicate discussion.}} it indicates that the object is a [[Constant (computer programming)|constant]]: its [[Value (computer science)|value]] may not be changed, unlike a [[variable (computer science)|variable]]. This basic use – to declare constants – has parallels in many other languages.
 
However, unlike in other languages, in the C family of languages the <code>const</code> is part of the ''type'', not part of the ''object''. For example, in C, {{code|2=c|1=int const x = 1;}} declares an object <code>x</code> of <code>int const</code> type – the <code>const</code> is part of the type, as if it were parsed "(int const) x" – while in [[Ada (programming language)|Ada]], {{code|2=ada|1=X : constant INTEGER := 1_}} declares a constant (a kind of object) <code>X</code> of <code>INTEGER</code> type: the <code>constant</code> is part of the ''object'', but not part of the ''type''.
 
=
This has two subtle results. Firstly, <code>const</code> can be applied to parts of a more complex type – for example, <code>int const * const x;</code> declares a constant pointer to a constant integer, while <code>int const * x;</code> declares a variable pointer to a constant integer, and <code>int * const x;</code> declares a constant pointer to a variable integer. Secondly, because <code>const</code> is part of the type, it must match as part of type-checking. For example, the following code is invalid:
<syntaxhighlight lang=cpp>
void f(int& x);
// ...
int const i;
f(i);
</syntaxhighlight>
because the argument to <code>f</code> must be a ''variable'' integer, but <code>i</code> is a ''constant'' integer. This matching is a form of [[program correctness]], and is known as '''const-correctness'''. This allows a form of [[programming by contract]], where functions specify as part of their [[type signature]] whether they modify their arguments or not, and whether their [[return value]] is modifiable or not. This type-checking is primarily of interest in pointers and references – not basic value types like integers – but also for [[composite data type]]s or templated types such as [[Container (abstract data type)|containers]]. It is concealed by the fact that the <code>const</code> can often be omitted, due to [[type coercion]] (implicit [[type conversion]]) and C being [[call-by-value]] (C++ and D are either call-by-value or call-by-reference).
 
== Consequences ==
The idea of const-ness does not imply that the variable as it is stored in [[computer memory]] is unwritable. Rather, <code>const</code>-ness is a [[compile-time]] construct that indicates what a programmer ''should'' do, not necessarily what they ''can'' do. Note, however, that in the case of predefined data (such as <code>char const *</code> [[string literal]]s), C <code>const</code> is ''often'' unwritable.
 
== Distinction from constants ==
While a constant does not change its value while the program is running, an object declared <code>const</code> may indeed change its value while the program is running. A common example are read only registers within embedded systems like the current state of a digital input. The data registers for digital inputs are often declared as <code>const</code> and <code>[[volatile (computer programming)|volatile]]</code>. The content of these registers may change without the program doing anything (<code>volatile</code>) but you shall not write to them either (<code>const</code>).
 
== Other uses ==
In addition, a (non-static) member-function can be declared as <code>const</code>. In this case, the [[this (computer programming)|<code>this</code> pointer]] inside such a function is of type <code>object_type const *</code> rather than merely of type <code>object_type *</code>.<ref>{{cite web |url=http://eel.is/c++draft/class.this#:this,type_of |title=The <code>this</code> pointer |website=Draft C++ Standard |access-date=2020-03-30 |quote=The type of <code>this</code> in a member function whose type has a ''cv-qualifier-seq cv'' and whose class is <code>X</code> is “pointer to ''cv'' <code>X</code>”.}}</ref> This means that non-const functions for this object cannot be called from inside such a function, nor can [[field (computer science)|member variables]] be modified. In C++, a member variable can be declared as <code>[[mutable object|mutable]]</code>, indicating that this restriction does not apply to it. In some cases, this can be useful, for example with [[cache (computing)|caching]], [[reference counting]], and [[data synchronization]]. In these cases, the logical meaning (state) of the object is unchanged, but the object is not physically constant since its bitwise representation may change.
 
== Syntax ==
In C, C++, and D, all data types, including those defined by the user, can be declared <code>const</code>, and const-correctness dictates that all variables or objects should be declared as such unless they need to be modified. Such proactive use of <code>const</code> makes values "easier to understand, track, and reason about,"<ref>[[Herb Sutter]] and [[Andrei Alexandrescu]] (2005). ''C++ Coding Standards''. p. 30. Boston: Addison Wesley. {{ISBN|0-321-11358-6}}</ref> and it thus increases the readability and comprehensibility of code and makes working in teams and maintaining code simpler because it communicates information about a value's intended use. This can help the [[compiler]] as well as the developer when reasoning about code. It can also enable an [[optimizing compiler]] to generate more efficient code.<ref>{{cite web|url=https://lkml.org/lkml/2013/1/12/139 |title=Why is the kfree() argument const? |publisher=lkml.org |date=2013-01-12}}</ref>
 
=== Simple data types ===
For simple non-pointer data types, applying the <code>const</code> qualifier is straightforward. It can go on either side of some types for historical reasons (for example, <code>const char foo = 'a';</code> is equivalent to <code>char const foo = 'a';</code>). On some implementations, using <code>const</code> twice (for instance, <code>const char const</code> or <code>char const const</code>) generates a warning but not an error.
 
=== Pointers and references ===
For pointer and reference types, the meaning of <code>const</code> is more complicated – either the pointer itself, or the value being pointed to, or both, can be <code>const</code>. Further, the syntax can be confusing. A pointer can be declared as a <code>const</code> pointer to writable value, or a writable pointer to a <code>const</code> value, or <code>const</code> pointer to <code>const</code> value. A <code>const</code> pointer cannot be reassigned to point to a different object from the one it is initially assigned, but it can be used to modify the value that it points to (called the ''pointee''). Reference variables in C++ are an alternate syntax for <code>const</code> pointers. A pointer to a <code>const</code> object, on the other hand, can be reassigned to point to another memory ___location (which should be an object of the same type or of a convertible type), but it cannot be used to modify the memory that it is pointing to. A <code>const</code> pointer to a <code>const</code> object can also be declared and can neither be used to modify the pointee nor be reassigned to point to another object. The following code illustrates these subtleties:
 
<syntaxhighlight lang=c>
void Foo( int * ptr,
int const * ptrToConst,
int * const constPtr,
int const * const constPtrToConst )
{
*ptr = 0; // OK: modifies the "pointee" data
ptr = NULL; // OK: modifies the pointer
 
*ptrToConst = 0; // Error! Cannot modify the "pointee" data
ptrToConst = NULL; // OK: modifies the pointer
 
*constPtr = 0; // OK: modifies the "pointee" data
constPtr = NULL; // Error! Cannot modify the pointer
 
*constPtrToConst = 0; // Error! Cannot modify the "pointee" data
constPtrToConst = NULL; // Error! Cannot modify the pointer
}
</syntaxhighlight>
 
==== C convention ====
Following usual C convention for declarations, declaration follows use, and the <code>*</code> in a pointer is written on the pointer, indicating [[dereferencing]]. For example, in the declaration <code>int *ptr</code>, the dereferenced form <code>*ptr</code> is an <code>int</code>, while the reference form <code>ptr</code> is a pointer to an <code>int</code>. Thus <code>const</code> modifies the ''name'' to its right. The C++ convention is instead to associate the <code>*</code> with the type, as in <code>int* ptr,</code> and read the <code>const</code> as modifying the ''type'' to the left. <code>int const * ptrToConst</code> can thus be read as "<code>*ptrToConst</code> is a <code>int const</code>" (the value is constant), or "<code>ptrToConst</code> is a <code>int const *</code>" (the pointer is a pointer to a constant integer). Thus:
<syntaxhighlight lang=c>
int *ptr; // *ptr is an int value
int const *ptrToConst; // *ptrToConst is a constant (int: integer value)
int * const constPtr; // constPtr is a constant (int *: integer pointer)
int const * const constPtrToConst; // constPtrToConst is a constant (pointer)
// as is *constPtrToConst (value)
</syntaxhighlight>
 
==== C++ convention ====