char str[] をポインタで参照したときの挙動が分からない


プログラムのデバッグに関して2つ解決したいプログラムがあります。  
環境はvisual studio 2019 Windows10 64bitです。

疑問点。なぜデバッグ中のstr[]の中は "str == NULL"しか書いていないのか、  
char str[] = "str == NULL ? "(NULL)" : str";より、str[] の中には"str == NULL ?
"(NULL)" : str"が入っていると思っていましたがデバッグしてみるとそうでないとわかりました。 **なぜstr[]の文字列が "str ==
NULL ? "(NULL)"ではなくずっと"str == NULL のままなのかわかりません。**  
一回目のループで中身はstr == NULL ? "(NULL)" : str、二回目のループでstr == NULL  
三回目のループでstr == NULLとなんだか想像したのと違った結果になります。

もう一つのプログラムに関してはstr[]の文字列は  
char* p = str[]によりpのアドレスに入ったはずなのに、デバッグするとなぜかstr[]の文字列が"abcde"ではなく、  
最初はchar str[] = { "abcde" };の中身はabcdeでしたが、一回目のループでbbcde、二回目でbccde、三回目bcdde  
四回目bcdeeと変わっていきます。 **なぜ`char* p`にstr[]の文字列を入れたのにstr[]の文字列まで変化するのかわかりません。**

一つ目のコード

[code]

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char str[] = "str == NULL ? \"(NULL)\" : str";
        char* p, * q;
        int ch;
        p = str;
        for (;;) {
            for (q = p; !(*q == '?' || *q == ':' || *q == 0); q++);
            ch = *q;
            *q = 0;
            printf("|%s|\n", p);
            if (ch == 0) break;
            p = q + 1;
        }
    }
    
[/code]

二つ目のコード

[code]

    #include <stdio.h>
    int main(void) {
        char str[] = "abcde";
    
        for (char* p = str; *p; ++p)
        {
            ++(*p);
            printf("%s\n", &(*p));
        }
    }
    
[/code]




キーワード  
メモリ。ポインター。参照。終端文字。NULL。

[code]

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        /* メモリ上に以下の文字列と最後尾にNULLを確保します。 */
        char str[] = "str == NULL ? \"(NULL)\" : str";
    
        /* strの確保されているメモリアドレスにアクセスする */
        /* 用途として、ポインターを２つ用意します。*/
        char* p, * q;
        /* strで確保されたメモリアドレスの終端まで達したことを判断する */
        /* ための変数です。無限ループを止めるための判断材料になります */
        int ch;
        /* ポインターpをstrで確保された最初のアドレスに設定します。*/
        p = str;
    
        /* 無限ループです。breakするまで止まりません。 */
        for (;;) {
            /* もう一つのループです */
            /* pが示すstrで確保されたアドレスから、順番に参照します */
            /* 中身が ? または : または終端NULLでなければ、ループは続きます。*/
            /* つまりqの指すアドレスは、strで参照できる中身が?:NULLまで一つずつ進んでいきます。*/
            for (q = p; !(*q == '?' || *q == ':' || *q == 0); q++);
            /* chに*qの中身を一旦保存しています。0の場合のみ、後でbreakして無限ループから抜け出します。*/
            ch = *q;
            /* *qの中身を0に置き換えています。これによって、strの中身が書き換わります */
            *q = 0;
            /* *p(最初はstrの先頭)からNULLまでを表示しています。 */
            /* 後半の処理で、pのアドレスは進められています */
            printf("|%s|\n", p);
            /* 無限ループを抜け出す処理です。*/
            /* これが正常に記述できないと無限ループでプログラムが止まりません。*/
            if (ch == 0) break;
            /* strの最初を示していたpのアドレスをq+1に書き換え、参照先を進めています*/
            /* これによって、上のprintfで表示するメモリアドレスも進みます */
            p = q + 1;
        }
    }
    
    
    
[/code]

[code]

    #include <stdio.h>
    int main(void) {
        /*str[]でメモリ上に５文字分の連続したアドレスを確保し、中身をabcdeとします。*/
        char str[] = "abcde";
    
        /* strで確保された最初のメモリアドレスから一つずつ参照していきます。
        /* NULLが出るまでループは終わらない。*/
        /* このループで1文字目から終端NULLまで。2文字目から終端NULLまでと順に表示します */
        for (char* p = str; *p; p++)
        {
        /* pointer *pはstr[]で確保されたメモリ上のアドレスの中身を直接操作する仕組みです。 */
        /* str[]で確保されたメモリアドレスを直接操作できる仕組みが ポインターです。 */
            /* *pで示されているメモリアドレスの値を取り出して、そこにプラス１します */
            /* それを*pで示されているアドレスに代入しています。strで確保されたメモリの中身が書き換わります。 */
            (*p) = (*p) + 1;
            /* *pで示しているアドレスから、終わりのNULLまでを表示します。*/
            printf("*p:%s\n", &(*p));
            /* strの中身も表示します。 */
            printf("str:%s\n", str);
        }
    }
    
[/code]

