blob: 9fe86ef4cb46750b3af5b1a157c7958c82ad75fe (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
+++
title = "C: the const modifier"
date = 2024-08-23
[extra]
latex = true
+++
---
### The `C` `const` modifier with nested pointers
The `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_
```C
/* 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:
```C
#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!
}
```
|