{"id":428,"date":"2010-10-22T07:47:39","date_gmt":"2010-10-22T14:47:39","guid":{"rendered":"http:\/\/www.airs.com\/blog\/?p=428"},"modified":"2010-10-22T07:47:39","modified_gmt":"2010-10-22T14:47:39","slug":"const","status":"publish","type":"post","link":"https:\/\/www.airs.com\/blog\/archives\/428","title":{"rendered":"const"},"content":{"rendered":"<p>It took me a long time to understand that the <code>const<\/code> qualifier in C is overloaded.  There was no <code>const<\/code> when I first learned C.  It was introduced in the C90 standard.  It was copied from C++, although the meaning of <code>const<\/code> is subtly different in the two languages.<\/p>\n<p>The first meaning of <code>const<\/code> in C is to use it to qualify a variable definition.  If you do that, it means that the variable can not be changed; it is immutable.  It can have an initializer but will never have another value.  A global or static <code>const<\/code> variable may be placed in read-only memory.<\/p>\n<p>The second meaning is to use it to qualify a pointer.  In this usage it means that the program may not change the value being pointed to by using the pointer.  However, it does not mean that that value is immutable, as it may be changed by a different pointer, or by a function call, or by casting away the <code>const<\/code> qualifier.<\/p>\n<p>The first meaning of <code>const<\/code> has a real effect on the program.  A variable declared <code>const<\/code> may be compiled differently from a variable which is not declared <code>const<\/code>.  The second meaning of <code>const<\/code>, on the other hand, is, in effect, compiler-enforced documentation.  The compiler will issue an error if an attempt is made to change a value using a <code>const<\/code> qualified pointer, but declaring such a pointer will not change the generated code.<\/p>\n<p>Although <code>const<\/code> qualified pointers are just documentation, in practice they are used far more often than <code>const<\/code> variables.  When the C90 standard came out and C compilers started supporting <code>const<\/code>, programmers spoke of <code>const<\/code>-poisoning: the feeling that once you use the <code>const<\/code> qualifier anywhere, it spread throughout your program as it had to be tracked through all assignments and function calls to avoid compiler warnings.  Adding <code>const<\/code>-poisoning to a program does not make it any more correct or reliable.  It&#8217;s just documentation, albeit documentation that the compiler enforces.<\/p>\n<p>One can imagine a range of different types of documentation which it might be nice to have the compiler enforce.  Perhaps it would be useful to know the alignment of a generic pointer, or to know that this <code>char*<\/code> pointer points to a null terminated string while that one points to a block of arbitrary bytes.  A program can use a <code>typedef<\/code> to indicate the intended meaning of some value, but a pointer to one <code>typedef<\/code> can be assigned to a pointer to a different <code>typedef<\/code> with no warning if the underlying types happen to be the same.  Why do we get compiler warnings for <code>const<\/code> pointers but not for <code>typedef<\/code> pointers?  It&#8217;s because <code>const<\/code> was added to the type system, whereas <code>typedef<\/code>, despite its name, is merely an aliasing mechanism, and is not part of the type system at all.<\/p>\n<p>It did not have to be this way.  It would have been possible to make <code>const<\/code> a storage specifier, like <code>static<\/code>, rather than a type qualifier.  It would have simply meant that the variable was immutable.  The address of a <code>const int<\/code> would have type <code>int *<\/code> rather than <code>const int *<\/code>.<\/p>\n<p>The C90 standard introduced one other type qualifier: <code>volatile<\/code> (in fact, the standard introduced the whole idea of type qualifiers).  Unlike <code>const<\/code>, the standard did not define the meaning of a <code>volatile<\/code> qualified pointer.  The address of a <code>volatile<\/code> variable has a <code>volatile<\/code> qualified pointer type, but the standard never said what the compiler should do with such a type.  It only says that any access to a <code>volatile<\/code> variable must be through an lvalue with the <code>volatile<\/code> qualifier.<\/p>\n<p>The C99 standard adds a third type qualifier, <code>restrict<\/code>, which is another can of worms.<\/p>\n<p>In retrospect I think that adding the <code>const<\/code> qualifier to the type system was a mistake.  It lets the compiler enforce a specific type of documentation but doesn&#8217;t let the program define the types of documentation that it cares about.  The documentation is not reliable as programs can cast away the qualifier, and indeed the standard requires basic functions like <code>strchr<\/code> to do exactly that.<\/p>\n<p>If you want the compiler to be able to check type attributes, then give the language a way to define the attributes that matter to a particular program.  If you want to compiler to be able to put a variable in a specific type of storage, such as a read-only data section, then use a storage specifier.  There is no need to mix the two ideas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It took me a long time to understand that the const qualifier in C is overloaded. There was no const when I first learned C. It was introduced in the C90 standard. It was copied from C++, although the meaning of const is subtly different in the two languages. The first meaning of const in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-428","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/posts\/428","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/comments?post=428"}],"version-history":[{"count":2,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/posts\/428\/revisions"}],"predecessor-version":[{"id":431,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/posts\/428\/revisions\/431"}],"wp:attachment":[{"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/media?parent=428"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/categories?post=428"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.airs.com\/blog\/wp-json\/wp\/v2\/tags?post=428"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}