C++の「++*p」「*p++」「*++p」の違いをわかりやすく解説
C++では、ポインタとインクリメント演算子を組み合わせた「*ptr++」「*++ptr」「++*ptr」は、一見よく似ていますが、動作はまったく異なります。本記事では、これら3つの式の違いを、演算子の優先順位の観点から具体例とともに解説します。
前置「++」と後置「++」の優先順位
まず、CおよびC++における演算子の優先順位を確認しておきましょう。
- 前置インクリメント「++」や前置デクリメント「--」は、間接参照演算子「*」よりも高い優先順位を持ちます。
- 後置インクリメント「++」や後置デクリメント「--」は、前置「++」および間接参照演算子「*」のどちらよりも高い優先順位を持ちます。
このため、ptrがポインタである場合、「*ptr++」は「*(ptr++)」と解釈され、「++*ptr」は「++(*ptr)」と解釈されます。括弧の付け方ひとつで意味が変わる点がポイントです。
例1:++*ptr —— 参照先の「値」をインクリメント
#include<iostream>
using namespace std;
int main() {
char arr[] = "Hello World";
char *ptr = arr;
++*ptr;
cout << *ptr;
return 0;
}
実行結果
I
この例では、最初にptrは配列の先頭文字「H」を指しています。「++*ptr」は「++(*ptr)」と解釈されるため、増分されるのはポインタではなく参照先の値です。その結果、「H」が1増えて「I」になります。ポインタ自身は移動しない点に注意してください。
例2:*ptr++ —— ポインタを後置インクリメント
#include<iostream>
using namespace std;
int main() {
char arr[] = "Hello World";
char *ptr = arr;
*ptr++;
cout << *ptr;
return 0;
}
実行結果
e
「*ptr++」は「*(ptr++)」と解釈されます。後置インクリメントの優先順位が最も高いため、ポインタptrがまず1つ先に進みます。その結果、この文の実行後にはptrは次の要素「e」を指しているため、出力は「e」になります。
例3:*++ptr —— ポインタを前置インクリメント
#include<iostream>
using namespace std;
int main() {
char arr[] = "Hello World";
char *ptr = arr;
*++ptr;
cout << *ptr;
return 0;
}
実行結果
e
「*++ptr」の場合も、前置「++」の優先順位が間接参照「*」より高いため、まずポインタが次の要素へ移動し、その後に「*」でその位置の値を取得します。したがって、こちらも出力は「e」です。
まとめ:3つの式の違い一覧
| 式 | 実際の解釈 | 動作 |
|---|---|---|
| ++*ptr | ++(*ptr) | 参照先の値を1増加させる(ポインタは移動しない) |
| *ptr++ | *(ptr++) | ポインタを1つ先へ進める(式の値としては元の位置を参照) |
| *++ptr | *(++ptr) | 先にポインタを1つ進めてから、新しい位置の値を参照する |
「++」が適用される対象が「値」なのか「ポインタ」なのかを見極めれば、混同しやすいこれらの式も正確に使い分けられるようになります。
-
C++における「struct」と「typedef struct」の違いとは?
```html 結論:C++では両者に実質的な違いはない C++において、「struct」を使った宣言と「typedef struct」を使った宣言の間には、実質的な違いがありません。その理由は、C++ではstruct、union、enum、classによるすべての宣言が、暗黙的にtypedefされたものと同じように扱われるためです。ただし、同じ名前を持つ別の宣言によってその名前が隠されている場合を除きます。 なぜ違いが生まれないのか C言語では、構造体を宣言しただけでは型名として直接使えず、「struct タグ名」という形式で記述する必要がありました。そのため、変数宣言のたびにstructキ
-
C++の文字リテラルと文字列リテラルの違いをわかりやすく解説
C++における文字リテラルと文字列リテラルの基本C++では、シングルクォート( )で囲まれた1文字は「文字リテラル」として扱われ、その型は char になります。例えば a は char 型であり、ASCIIベースのシステムでは整数値 97 を持ちます。一方、ダブルクォート( )で囲まれた1文字または複数文字の並びは「文字列リテラル」として扱われます。その型は const char[] であり、実体は「文字列の長さ + 1」のサイズを持つ配列です。この余分な1文字分は、文字列の終端を示すヌル文字(\0)として確保されています。具体的な違いのポイント文字リテラル: 原則として1文字のみを格納する