Search code examples
cpointersconst-correctness

Why is an implicit conversion from non-const to const allowed for pointers in the first place?


I understand that implicit conversion from non-const to const is not dangerous when handling values, by example:

int mutable = 5;
const int immutable = mutable;

However, when working with pointers, I can do something as follows:

int some_number = 5;
int *mutable = &some_number;
const int *immutable = mutable;    // <= Legal, but isn't it dangerous?

// Let's try to break const
printf("%d\n", *immutable);        // Prints 5
mutable[0] = 10;
printf("%d\n", *immutable);        // Prints 10

By the way, for double pointers this is not allowed (at least you get a warning)! See this question and the references therein.


Solution

  • From the C11 standard (draft N1570):

    6.7.3 Type qualifiers

    Syntax

    1. type-qualifier:
      const
      restrict
      volatile
      _Atomic

    [...]

    Semantics:

    1. The properties associated with qualified types are meaningful only for expressions that are lvalues.

    [...]

    EXAMPLE 1

    An object declared

    extern const volatile int real_time_clock;
    

    may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.

    In simple terms:

    const doesn't mean a value never changes. It only means that you are not allowed to change it1.

    For callees , const is a restriction, not a promise.
    For callers however, it is a promise. Passing a const pointer to a function, you can safely assume that the function will not change your data2, thus is "making a promise to you".


    1 ...through the identifier with the const qualifier.
    2 ...through the const argument passed to it.