Constness

Arrays and pointers

Intact values

Values of the array cannot be changed. But array itself can be reassigned

int main(int argc, char const *argv[])
{
    const char* const_variable = nullptr;
    const_variable = new char[5];
    // const_variable[0] = 'H'; // error: expression must be a modifiable lvalue
    delete[] const_variable;
    return 0;
}

Intact pointer

This preserves the pointer but not the values

int main(int argc, char const *argv[])
{
    char* const const_variable = nullptr;
    // const_variable = new char[5]; // error: expression must be a modifiable lvalue
    const_variable[0] = 'H';
    delete[] const_variable;
    return 0;
}

So it must be initialized (assigned) only once. You cannot change size of the array, but content can be modified.

int main(int argc, char const *argv[])
{
    char* const const_variable = new char[5];
    const_variable[0] = 'H';
    const_variable[1] = 'e';
    const_variable[2] = 'l';
    const_variable[3] = 'l';
    const_variable[4] = 'o';
    delete const_variable;
    // cons[]t_variable = nullptr; // error: expression must be a modifiable lvalue
    return 0;
}

Read-only

Here's the absolute read-only version

int main(int argc, char const *argv[])
{
    const char* const const_variable = new char[5];
    // const_variable[0] = 'H'; // error: expression must be a modifiable lvalue
    delete[] const_variable;
    // const_variable = nullptr; // error: expression must be a modifiable lvalue
    return 0;
}

When function changes the pointer

How to make sure that a pointer you have is not going to change? For example, if the function reads elements from an array and will update the pointer to the position where it finished reading.

unsigned char* key = NULL;
size_t size = key_size;
OSSL_DECODER_from_data(dctx, key, &size);
// int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata, size_t *pdata_len);

Wrong

const unsigned char **data = const_cast<const unsigned char**>(&key); // data pointer will be changed
OSSL_DECODER_from_data(dctx, data, &size);

Correct

const unsigned char *data = const_cast<const unsigned char*>(key);
OSSL_DECODER_from_data(dctx, &data, &size);

What is const in const unsigned char *data vs const unsigned char **data?