C言語でconst束縛によるimmutable表現をやりたい
constの作用についておさらい
ポインタ型での意味合いについては下記、記事参照
https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F235904%2F9baaeb28-dca2-908d-4ac1-64ea2ee5f67b.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=92e01f5dafd387b0ceb153d1c5f723a4
https://ricapitolare.vercel.app/svg?url=https://qiita.com/mizcii/items/35df2bceac67a75f75dd#.svg https://qiita.com/mizcii/items/35df2bceac67a75f75dd
https://ricapitolare.vercel.app/svg?url=https://qiita.com/yuki12/items/06c85af2735ddefd5666#.svg https://qiita.com/yuki12/items/06c85af2735ddefd5666
覚え方としては、*(アスタリスク)は「その左側すべてに係る」と考えるのが一番わかりやすい。
table:const×pointar type
宣言 意味合い 値変更 ポインタ変更
const uint8_t 読み取り専用の整数 ❌️ ⭕️
uint8_t* 整数へのポインタ ⭕️ ⭕️
const uint8_t* 読み取り専用の整数へのポインタ ❌️ ⭕️
uint8_t* const ポインタ自体が読み取り専用の整数へのポインタ ⭕ ❌️
const uint8_t* const 読み取り専用の整数を読み取り専用にする ❌️ ❌️
uint8_t const* const 整数を読み取り専用にして不変にする ❌️ ❌️
⭕:変更可能
❌️:変更不可
code: const_example.c
void foo(void) {
const uint8_t v = 10;
// v = 20; // ✕ コンパイルエラー:再代入不可
uint8_t a = 5;
uint8_t * p1 = &a;
*p1 = 6; // OK
p1 = &v; // OK
const uint8_t * p2 = &v;
// *p2 = 7; // ✕ コンパイルエラー:*p2はconst
p2 = &a; // OK
uint8_t * const p3 = &a;
*p3 = 8; // OK
// p3 = &v; // ✕ コンパイルエラー:p3自体はconst
const uint8_t * const p4 = &v;
// *p4 = 9; // ✕
// p4 = &a; // ✕
}
immutableにより再代入を防ぎたい理由
C言語での実装例
関数の入力パラメータでconst束縛する
入力専用パラメータであることを明示する
void process(const uint8_t* data size_t n)
呼び出し側のバッファを関数内で変更しないことを保証する関数
ポインタ自体を不変にする
void initalize(char* const buf, size_t n)
bufの指し先である値は変更可能だが、buf自体を別のアドレスに変更できない
入力する値を再代入不可であることを保証
void add(const int x, const int y)
関数内でx=...、y=...できないようにする
計算結果をconst束縛する
code:calculate.c
#include <stdio.h>
#icnlude <stdint.h>
uint64_t add(uint32_t x, uint32_t y
{
return (const uint64_t)x + y;
}
void main(void)
{
const uint64_t add_result = add(123,456);
// add_rseult = 0; // add_resultに再代入しようtするとコンパイルエラー
printf("%d \n",add_result);
}