文字列とconst

文字列がメモリのどの領域に配置されるか実験
#include <stdio.h>

char *p = "abc";
char *q = "abc";
const char s[] = "abc";

int main(void) {
    char *r = "abc";

    printf("p: %p   %p\n", p, &p);
    printf("q: %p   %p\n", q, &q);
    printf("r: %p   %p\n", r, &r);
    printf("s: %p\n", s);
    
    return 0;
}

出力結果
p: 0x10a938f04 0x10a939068
q: 0x10a938f04 0x10a939070
r: 0x10a938f04 0x7fff6a537b00
s: 0x10a938f08

文字列p、q、rが指す0x10a938f04と配列sのアドレス0x10938f08は読み取り専用の静的記憶領域(ROM領域)に置かれている。p、qのアドレス0x10a939068と0x10a939070は読み書き可能な静的記憶領域に置かれ、rのアドレス0x7fff6a537b00はスタックに置かれている

この時に、q[1]='@';等して値を変更しようとすると実行時にエラーが発生する。
これをコンパイル時に検出する為には変数qの宣言にconstを付ける

const char *q = abc
constの動作についてまとめ

constは必ず定数を意味するものではない。

char *my_strcpy(char *dest, const char *src) {
    src = NULL;
}

srcに代入しているのにコンパイルエラーにならない。

この時、読み取り専用になっているのは「src」ではなく「srcが指す先にあるもの

char *my_strcpy(char *dest, const char *src) {
    *src = 'a';  
}

この場合エラーになる

「src」そのものを読み取り専用にするなら

char *my_strcpy(char *dest, char * const src) {
    src = NULL;  
}

この場合代入ができずエラーとなる

「src」と「srcの指す先にあるもの」を読み取り専用にするなら

char *my_strcpy(char *dest, const char * const src) {
    src = NULL;  
    *src = 'a';
}

この場合は両方ともエラーになる