2024-08-23
C
const
modifier with nested pointersThe const
is a way to tell the C
compiler to consider the target variable read-only.
On function declaration, the data arguments are de facto const
, but we could specify the pointers' behavior as seen below.
The key is to apply the const
modifier from right to left
/* August 2024, C99.
* Const modifier to data pointers.
* Note: the patterns are just layers of Pascal's binomial triangle,
* easy to repete for a growing number of stars.
*/
/*
* Zero star.
*/
/* Zero const modifier -> 1 choose 0. */
static int data;
/* One const modifier -> 1 choose 1. */
static int const constData;
/*
* One star
*/
/* Zero const modifier -> 2 choose 0. */
static int *ptr_data;
/* One const modifier -> 2 choose 1. */
static int const *ptr_constData;
static int *const constPtr_data;
/* Two const modifiers -> 2 choose 2. */
static int const *const constPtr_constData;
/*
* Two stars
*/
/* Zero const modifier -> 3 choose 0. */
static int **ptr_ptr_data;
/* One const modifier -> 3 choose 1. */
static int const **ptr_ptr_constData;
static int *const *ptr_constPtr_Data;
static int **const constPtr_ptr_Data;
/* Two const modifiers -> 3 choose 2. */
static int const *const *ptr_constPtr_constData;
static int const **const constPtr_ptr_constData;
static int *const *const constPtr_constPtr_data;
/* Three const modifiers -> 3 choose 3. */
static int const *const *const constPtr_constPtr_constData;
/*
* Three stars
*/
/* Zero const modifier -> 4 choose 0. */
static int ***ptr_ptr_ptr_data;
/* One const modifier -> 4 choose 1. */
static int const ***ptr_ptr_ptr_constData;
static int *const **ptr_ptr_constPtr_data;
static int **const *ptr_constPtr_ptr_data;
static int ***const constPtr_ptr_ptr_data;
/* Two const modifiers -> 4 choose 2. */
static int const *const **ptr_ptr_constPtr_constData;
static int const **const *ptr_constPtr_ptr_constData;
static int const ***const constPtr_ptr_ptr_constData;
static int *const *const *ptr_constPtr_constPtr_data;
static int *const **const constPtr_ptr_constPtr_data;
static int **const *const constPtr_constPtr_ptr_data;
/* Three const modifiers -> 4 choose 3. */
static int const *const *const *ptr_constPtr_constPtr_constData;
static int const *const **const constPtr_ptr_constPtr_constData;
static int const **const *const constPtr_constPtr_ptr_constData;
static int *const *const *const constPtr_constPtr_constPtr_data;
/* Four const modifiers -> 4 choose 4. */
static int const *const *const *const constPtr_constPtr_constPtr_constData;
We can then do the same for following stars depth, but as we can see the number of possibilities is combinatorial: for \(n\) stars-pointers we will have \(2^{n + 1}\) const
flavours possible.
You can verify the above assumptions by:
#include <stddef.h>
void foo(int *ptr_data, int const *ptr_constData, int *const constPtr_data, int const *const constPtr_constData)
{
*ptr_data = 0; // OK: modifies the pointed data
ptr_data = NULL; // OK: modifies the pointer
*ptr_constData = 0; // Error!
ptr_constData = NULL; // OK: modifies the pointer
*constPtr_data = 0; // OK: modifies the pointed data
constPtr_data = NULL; // Error!
*constPtr_constData = 0; // Error!
constPtr_constData = NULL; // Error!
}