ポインター式:* ptr ++、* ++ ptrおよび++ * ptr


128

最近、自分では理解できないこの問題に遭遇しました。

これらの3つの表現は本当に何ですか意味するのでしょうか?

*ptr++
*++ptr
++*ptr

リッチーを試しました。しかし、残念ながら、彼はこれらの3つの操作について彼が言ったことを追跡することができませんでした。

それらはすべて、ポインタ/ポイントされた値をインクリメントするために実行されることを知っています。評価の優先順位や順序についても多くのことがあると思います。最初にポインターをインクリメントしてからそのポインターのコンテンツをフェッチするように、単純にコンテンツをフェッチしてからポインターをインクリメントするなどです。ご覧のとおり、実際の操作について明確に理解していません。できるだけ早くクリアしてください。しかし、それらをプログラムに適用する機会を得たとき、私は本当に迷っています。例えば:

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

私にこの出力を与えます:

ello

しかし、私の期待はそれが印刷されることでしたHello。最後の1つのリクエスト-特定のコードスニペットで各式がどのように機能するかの例を教えてください。ほとんどの場合、理論のほんの一部だけが私の頭の上を飛んでいきます。


6
4つ目を見逃しました:((*ptr)++括弧を明確にするために必要な括弧*ptr++
user4815162342

15
印刷する前にポインタを増やしたからです。while(* p)およびprintf( "%c"、* p ++);
dcaswell 2013

インタビューのための素晴らしい質問。限られた実用性。Cにそのような指針がなかったらいいのに:)
Himanshu

5
@Himanshuインタビュイーのヌードルが焼けたら、次のことを試してください。一意の文字の有効な終了文字列を指すグローバルポインタを用意しますchar* p。次に、パラメータ、が指す現在の文字の両方fn(char ch)を出力する関数を用意します。今たinvoke Q:んは、同じ文字を印刷二回?何人の教授がその質問を間違っているのか驚くでしょう。chpfn(*p++);fn
WhozCraig 2013

1
pは文字列リテラルを指すので、記述する必要がありますconst char* p = "Hello";
hetepeperfan 2013

回答:


275

ここに私が役立つと思います詳細な説明があります。説明するのが最も簡単なプログラムから始めましょう。

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

最初のステートメント:

const char* p = "Hello";

pのポインタとして宣言しますchar。「ポインタへのchar」と言うとき、それはどういう意味ですか?これは、の値pがのアドレスであることを意味しcharます。pメモリ内のどこにを保持するためのスペースが確保されているかを示しますchar

ステートメントpは、文字列リテラルの最初の文字を指すように初期化されます"Hello"。この演習でpは、文字列全体を指すのではなく、最初の文字のみを指すと理解することが重要'H'です。結局のところ、文字列全体ではなく、p1へのポインタcharです。の値はin pのアドレスです。'H'"Hello"

次に、ループを設定します。

while (*p++)

ループ状態とは*p++どういう意味ですか?この問題を解決するために、3つのことが機能しています(少なくとも親しみが始まるまで)。

  1. 2つの演算子、postfix ++とindirection の優先順位*
  2. 後置インクリメント式の値
  3. 後置インクリメント式の副作用

1.優先順位。演算子の優先順位表をざっと見ると、postfixの増分の優先順位(16)が逆参照/間接参照(15)よりも高いことがわかります。つまり、複雑な式*p++は次のようにグループ化されます*(p++)。つまり、*部品は部品の値に適用されますp++。ので、取りましょうp++最初役割を。

2. Postfix式の値。値は、p++の値であるp 増分の前に。あなたが持っている場合:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

出力は次のようになります。

7
8

インクリメントの前にi++評価されるためi。同様p++に、の現在の値に評価されますp。ご存知のように、pはのアドレスです'H'

ので、p++部分は*p++評価されました。これはの現在の値ですp。その後、*部分が発生します。*(current value of p)つまり、が保持するアドレスの値にアクセスしますp。そのアドレスの値は'H'です。だから式*p++評価され'H'ます。

ちょっと待ってください。がと*p++評価された場合'H'、なぜ'H'上記のコードで出力されないのですか?それは副作用ですが発生します。

3. Postfix式の副作用。接尾辞に++は現在のオペランドのがありますが、そのオペランドをインクリメントするという副作用があります。え?そのintコードをもう一度見てください。

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

前述のように、出力は次のようになります。

7
8

ときにi++最初に評価されprintf()、それは第二の前にいくつかの点であること7と評価さしかし、Cの標準保証printf()実行を開始、副作用++オペレータが行われているでしょう。つまり、2番目printf()が発生する前に、次iの結果としてインクリメントされます。++に、最初のの演算子のprintf()。ちなみに、これは、標準が副作用のタイミングについて与える数少ない保証の1つです。

コードでは、式*p++が評価されると、に評価され'H'ます。しかし、あなたがこれに到達するまでには:

printf ("%c", *p)

その厄介な副作用が発生しました。p増加しました。うわあ!これに、もはやポイント'H'が、1文字の過去へ'H':へ'e'、つまりインチ それはあなたのコックファイされた出力を説明します:

ello

したがって、他の回答で役立つ(そして正確な)提案の合唱:受信した発音を印刷し、"Hello"コックニーの対応物を印刷しない場合は、次のようなものが必要です。

while (*p)
    printf ("%c", *p++);

そんなにたくさん。残りはどうですか?これらの意味について質問します。

*ptr++
*++ptr
++*ptr

最初の話をしたので、2番目の話を見てみましょう*++ptr

以前の説明で、接尾辞の増分p++には特定の優先順位、および副作用があることを確認しました。接頭辞の増分に++pは、その接尾辞の対応物と同じ副作用があります。それは、オペランドを1ずつ増分します。ただし、優先順位は異なります

接頭辞の増分は、接尾辞よりも優先順位が低くなります。優先順位は15です。つまり、逆参照/間接演算子と同じ優先順位*です。のような表現で

*++ptr

重要なのは優先順位ではありません。2つの演算子の優先順位は同じです。したがって、結合性が始まります。プレフィックスの増分と間接演算子には、右から結合性があります。その関連性のために、オペランドptrは、最も++左側の演算子の前に、最も右の演算子でグループ化され*ます。つまり、式はグループ化され*(++ptr)ます。したがって、*ptr++別の理由で、ここでも*パーツがパーツの値に適用されます++ptr

それで、その値は何ですか?接頭辞インクリメント式の値は、インクリメント後のオペランドの値です。これは、後置インクリメント演算子とは非常に異なる獣になります。あなたが持っているとしましょう:

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

出力は次のようになります。

8
8

... postfix演算子で見たものとは異なります。同様に、次の場合:

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

出力は次のようになります。

H e e l                // good dog

なぜか分かりますか?

次に、あなたが尋ねた3番目の式に到達します++*ptr。実際、それは多くの中で最も扱いにくいものです。両方の演算子の優先順位は同じで、関連付けは右から左です。つまり、式はグループ化され++(*ptr)ます。++一部はの値に適用されます*ptr一部。

だから私たちが持っている場合:

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

驚くほど自己中心的な出力は次のようになります。

I

何?!わかりましたので、*pパーツはに評価され'H'ます。次に、++が出てきます。その時点で'H'、ポインタには適用されず、に適用されます。に1を追加するとどうなります'H'か?1とASCII値'H'72が加算されます。73を取得します。これをとして表すと、ASCII値73でcharが取得されます。char'I'

これで、質問で尋ねた3つの表現が処理されます。あなたの質問への最初のコメントで言及されている別のものがあります:

(*ptr)++ 

それも面白いです。あなたが持っている場合:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

それはあなたにこの熱狂的な出力を与えます:

HI

どうしたの?繰り返しますが、これは優先順位式の値、および副作用の問題です。括弧があるため、*pパーツは1次式として扱われます。一次表現は他のすべてに勝ります。彼らは最初に評価されます。そして*p、ご存知のとおり、はに評価され'H'ます。式の残りの部分である++部分がその値に適用されます。したがって、この場合はに(*p)++なり'H'++ます。

の価値は'H'++何ですか?あなたが言ったなら'I'、あなたは(すでに!)後置インクリメントによる価値対副作用の私たちの議論を忘れました。'H'++は、の現在の値に 評価されることに注意してください'H'。そのため、最初printf()に印刷します'H'。次に、副作用として、それ'H'はに増分され'I'ます。2番目printf()はそれを出力し'I'ます。そして、あなたはあなたの陽気な挨拶を持っています。

大丈夫ですが、最後の2つのケースでは、なぜ私は必要ですか

char q[] = "Hello";
char* p = q;

なぜ私はただのようなものを持てないのですか

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

なぜなら"Hello"、文字列リテラルだからです。++*pあなたがしようとした場合、あなたは変更しようとしています'H'文字列のをて、文字列'I'全体を作成ています"Iello"。Cでは、文字列リテラルは読み取り専用です。それらを変更しようとすると、未定義の動作が呼び出されます。"Iello"英語でも未定義ですが、それは単なる偶然です。

逆に、

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

何故なの?この場合、pは、配列です。配列は変更可能なl値ではありません。p配列の名前は定数ポインタのように機能するため、事前または事後の増分または減分によってポイントを変更することはできません。(それは実際にはそうではありません。これは、それを見るのに便利な方法です。)

要約すると、あなたが尋ねた3つのことはここにあります:

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

そして、4つ目は、他の3つと同じくらい楽しいものです。

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

1つ目と2つ目は、 ptrが実際に配列識別子であるます。3番目と4番目はptr、文字列リテラルを指す場合にクラッシュします。

そこにあります。私はそれが今すべての結晶であることを望みます。あなたは素晴らしい聴衆でした、そして私は一週間ここにいます。


22
このフォーラムに行く前に、自分が所有している「C」の本を3つ検索しました。いくつかの注目すべきオンラインチュートリアルも試しました。しかし、それらのどれもあなたの説明に近づきません(特に、すべてをまとめた方法)。あなたは私が尋ねた質問に答えただけでなく、草の根レベルから多くのことを話し合った。実際、あなたは今日、私が以前欠けていた基本的なことをたくさん教えてくれました。受け入れられた答えを切り替えるしかなかった。:) 再度、感謝します。
割り当て

26
+1これは、SOで読んだ最良の回答だと思います。誰もがこの答えから多くを学ぶことができたと思います。
Shafik Yaghmour 2013

9
あなた先生、C.の本書くべき
ディロンバートン

1
良い質問に対するなんて美しい答えでしょう!@verboseよくやった!
benka 2013年

7
@verboseあなた、あなたの名に恥じない.. :)
sleeping_dragon

44

ptrがarrayのi番目の要素を指しているとしarrます。

  1. *ptr++を評価し、の(i + 1)番目の要素を指すようにarr[i]設定ptrarrます。と同等*(ptr++)です。

  2. *++ptrptrの(i + 1)番目の要素を指すように設定しarr、に評価されarr[i+1]ます。と同等*(++ptr)です。

  3. ++*ptrarr[i]1ずつ増加し、その増加した値に評価されます。ポインターptrはそのままです。と同等++(*ptr)です。

さらにもう1つありますが、それを書くには括弧が必要です。

  1. (*ptr)++ 増加する arr[i]1ずつ、する前の値に評価されます。ポインターptrは再びそのままになります。

あなたが自分で理解できる残りの部分。@Jaguarも回答しました。


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

プリインクリメントおよびポストインクリメントの演算子については、こちらをお読みください


これはHello出力として与え られます

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}

@ Nik-Lzはい、出力はHello
Jainendra

7

ループの状態が悪いです:

while(*p++)
    printf("%c",*p);

と同じです

while(*p)
{
    p++;
    printf("%c",*p);
}

そしてそれは間違っています、これは次のようになります:

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++同じです*(ptr++)

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptr同じです*(++ptr)

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptr同じです++(*ptr)

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)

私は答えの最初の部分に完全に同意します。2番目の部分では、(整数への)ポインターを整数で初期化することは、ポインターの使用法を理解するのに苦労している人を混乱させます。
nickie 2013

4

あなたは優先順位について正しい、 *は接頭辞の増分より優先されますが、後置の増分より優先されない。これらの内訳は次のとおりです。

*ptr++ -左から右に進み、ポインターを逆参照し、ポインター値をインクリメントします(逆参照よりもpostfixの優先順位が高いため、ポインターの値ではありません)。

*++ptr -ポインタをインクリメントしてから逆参照します。これは、プレフィックスと逆参照の優先順位が同じであるため、右から左の順に評価されるためです

++*ptr-優先度に関して上記と同様に、ポインターを逆参照し、ポインターが指すものをインクリメントするために、再び右から左に移動します。あなたの場合、読み取り専用変数(char* p = "Hello";)を変更しようとしているため、これは未定義の動作につながることに注意してください。


3

他の答えは正しいのですが、何か欠けていると思うので、私の見方を追加します。

 v = *ptr++

手段

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

どこに

 v = *++ptr

手段

 ptr = ptr + 1
 v   = *ptr

ポストインクリメント(およびポストデクリメント)が意味することを理解することが重要です

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

なぜそれが重要なのですか?まあCではそれほど重要ではありません。C ++ではptr、イテレータのような複雑な型かもしれません。例えば

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

この場合、it複雑なタイプであるit++ため、temp作成のために副作用がある可能性があります。もちろん、運が良ければ、コンパイラは不要なコードを破棄しようとしますが、イテレータのコンストラクタまたはデストラクタが何かを実行すると、it++すると、作成時にこれらの効果が表示されますtemp

私が言おうとしていることが不足しているのは、Write What You Meanです。increment ptrを意味する場合は、++ptrnotと書き込みptr++ます。もし意味するならtemp = ptr, ptr += 1, tempptr++


0
*ptr++    // 1

これは次と同じです:

    tmp = *ptr;
    ptr++;

したがって、が指すオブジェクトの値ptrが取得されてから、ptrインクリメントされます。

*++ptr    // 2

これは次と同じです:

    ++ptr;
    tmp = *ptr;

したがって、ポインタptrがインクリメントされ、次に、が指すオブジェクトptrが読み取られます。

++*ptr    // 3

これは次と同じです:

    ++(*ptr);

したがって、が指すオブジェクトptrはインクリメントされます。ptr自体は変更されていません。


0

postfixとprefixは逆参照よりも優先順位が高いので

*ここでptr ++はptrの増分を投稿し、ptrの新しい値をポイントします

* ++ ptrここでPre Increment fist、次にptrの新しい値を指す

ここで++ * ptrは、最初にそのplauを指すptrの値を取得し、その値をインクリメントします


1
これは誤りです。Postfixは優先順位が高くなりますが、prefixは逆参照と同じ優先順位を持ちます。
2019

0

ポインター式:* ptr ++、* ++ ptrおよび++ * ptr:

:ポインターは初期化する必要があり、有効なアドレスが必要です。私たちのプログラム(a.out)とは別にRAMにあるので、同時により多くのプログラムが実行されています。

これを説明する前に、簡単な例を考えてみましょう。

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

上記のコードの出力を分析して、上記のコードの出力が得られることを願っています。上記のコードから明らかなことの1つは、ポインター名(ptr)はアドレスについて話していることを意味し、* ptrについて話していることを意味します / dataます。

ケース1* ptr ++、* ++ ptr、*(ptr ++)および*(++ ptr):

上記の4つの構文はすべて似ていますが、address gets incrementedアドレスがインクリメントされる方法が異なります。

:式を解くには、式に演算子がいくつあるかを調べ、次に演算子の優先順位を調べます。同じ優先度を持つ複数の演算子を使用して、右(R)から左(L)または左から右に可能性のある進化または結合性の順序を確認します。

* ptr ++:ここには2つの演算子、つまりde-reference(*)と++(increment)があります。両方が同じ優先度を持っている場合は、RからLまでの関連性を確認します。したがって、最初に来る演算子を問わず、右から左に解き始めます。

* ptr ++:最初の++はRからLへの解決中に来たため、アドレスは増加しますが、事後は増加します。

* ++ ptr:最初のアドレスと同じですが、アドレスも増分されますが、その前の増分です。

*(ptr ++):ここには3つの演算子があり、その中にグループ化()が最も優先度が高いため、最初にptr ++が解決されます。つまり、アドレスは増加しますが、ポストされます。

*(++ ptr):上記の場合と同じですが、ここでもアドレスは増分されますが、事前に増分されます。

ケース2++ * ptr、++(* ptr)、(* ptr)++:

上記の4つの構文はすべて類似しています。すべての値/データがインクリメントされますが、値がどのように変更されるかは異なります。

++ * ptr:最初の*はRからLに解くときに来たので、値は変更されますが、その前の増分です。

++(* ptr):上記の場合と同じで、値が変更されます。

(* ptr)++:ここには3つの演算子があり、その中にグループ化()が最も優先度が高く、Inside()* ptrがあります。したがって、最初に* ptrが解決されます。つまり、値がインクリメントされてポストされます。

:++ * ptrと* ptr = * ptr + 1はどちらも同じで、どちらの場合も値が変更されます。++ * ptr:1つの命令(INC)のみが使用され、シングルショットで直接値が変更されます。* ptr = * ptr + 1:ここでは、最初の値が増分され(INC)、次に割り当てられます(MOV)。

上記のポインターのインクリメントのさまざまな構文をすべて理解するには、単純なコードを考えてみましょう。

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

上記のコードで、コメントのコメント/コメント解除を試み、出力を分析します。

定数としてのポインタ:ポインターを定数として作成する方法はありませんが、ここでは触れません。

1)const int * p OR int const * p:ここでvalue定数アドレスは定数はありません。いくつかのアドレス?そのアドレスで値は何ですか?いくつかの価値は正しいですか?その値は定数ですが、その値を変更することはできませんが、ポインターがどこを指しているのですか?いくつかのアドレスは正しいですか?他のアドレスを指すこともできます。

これを理解するために、以下のコードを考えてみましょう:

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

上記のコードの出力を分析してみてください

2)int const * p:これは「**constant pointe**r」と呼ばれaddress is constant but value is not constantます。ここでは、アドレスを変更することはできませんが、値を変更できます。

:定数ポインター(上記の場合)は、宣言時に初期化する必要があります。

これを理解するために、簡単なコードを確認してみましょう。

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

上記のコードで++ * pまたは* p ++がないことがわかった場合、アドレスまたは値を変更していないためエラーが発生するため、これは単純なケースだと思われるかもしれません。どうして ?コメントで述べた理由。

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

それで、この問題の解決策は何ですか?

     int* const p = &x;

このケースの詳細については、以下の例を検討してみましょう。

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3)const int * const p:ここでは、アドレスと値の両方が定数です。

これを理解するには、以下のコードを確認してください

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

-1
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*pあなたがのASCII値インクリメントしようとしている手段*p

   is "Hello"
       ^
       | 
       p

定数なので、値をインクリメントできないため、エラーが発生します

あなたのwhileループと同様に、ループは(NULL)文字*p++がある文字列の終わりに達するまで実行されます'\0'

*p++最初の文字をスキップするので、2番目の文字からのみ出力が得られます。

次のコードは、whileループがあるので何も出力しません '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

次のコードは、次のコードと同じ出力、つまりelloを提供します。

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.