C++ ポインタの算術演算

C++ ポインタ

ポインタは数値で表されるアドレスです。したがって、ポインタに対して算術演算を実行できます。ポインタに対しては、++、--、+、- の4つの算術演算を行うことができます。

仮にptrはアドレス1000を指す整数型ポインタであり、32ビットの整数です。このポインタに対して次の算術演算を実行してみましょう:

ptr++

ptr++ を実行すると、ポインタ ptr は4バイト前方に移動し、次の整数型要素のアドレスを指します。これは、ポインタの算術演算がポインタの型とサイズに基づいて移動距離を決定するためです。この場合、32ビット整数ポインタであるため、各整数は4バイトを占め、ptr++ はポインタ ptr を4バイト前方に移動させ、次の整数型要素のアドレスを指します。

もしptrがアドレス1000の文字を指している場合、ptr++ を実行するとポインタ ptr の値は増加し、次の文字要素のアドレスを指します。ptr は文字ポインタであり、各文字は1バイトを占めるため、ptr++ は ptr の値を1増加させ、実行後 ptr はアドレス1001を指します。

ポインタ算術演算の詳細な解説:

  • 加算演算:ポインタに対して加算演算を行うことができます。ポインタpに整数nを加えると、結果はポインタpがn個の要素分前方に移動したものになります。例えば、pがint型のポインタで、各intが4バイトを占める場合、p + 1 はpが指す次のint要素を指します。

  • 減算演算:ポインタに対して減算演算を行うことができます。ポインタpから整数nを引くと、結果はポインタpがn個の要素分後方に移動したものになります。例えば、pがint型のポインタで、各intが4バイトを占める場合、p - 1 はpが指す前のint要素を指します。

  • ポインタとポインタの間の減算演算:2つのポインタ間の距離を計算できます。ポインタpから別のポインタqを引くと、結果は2つのポインタ間の要素数になります。例えば、pとqが2つのint型ポインタで、各intが4バイトを占める場合、p - q は2つのポインタ間の要素数になります。

  • ポインタと整数の間の比較演算:ポインタと整数を比較演算できます。関係演算子(<、>、<=、>=など)を使用して、ポインタと整数を比較できます。この比較は通常、ポインタが有効なメモリ位置を指しているかどうかを判断するために使用されます。

ポインタのインクリメント

C++では、ポインタはメモリアドレスを格納する変数です。ポインタをインクリメントすることは、ポインタを次のメモリ位置、通常は次の配列要素を指すようにすることを意味します。ポインタのインクリメントでは、ポインタが指すデータ型に基づいてポインタの値が自動的に調整されます。

例えば、ポインタがint型の配列要素を指している場合、ポインタをインクリメントすると次のint要素を指すようになります。以下は、ポインタをインクリメントする方法を示す簡単な例です:

例

#include <iostream> int main() { // 配列を定義する int arr[] = {10, 20, 30, 40, 50}; // 配列の最初の要素を指すポインタを定義する int* ptr = arr; // ポインタが指す要素を出力する std::cout << "ポインタが現在指している要素:" << *ptr << std::endl; // ポインタをインクリメントする ptr++; // ポインタが指す要素を出力する std::cout << "ポインタをインクリメントした後に指す要素:" << *ptr << std::endl; return 0; }

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

指针当前指向的元素: 10
递增指针后指向的元素: 20

この例では、ポインタptrは最初、配列arrの最初の要素を指しています。実行するとptr++、ポインタptrはインクリメントされ、配列の次の要素(つまり2番目の要素)を指すようになります。

ポインタをインクリメントするとき、ポインタの値は、ポインタが指すデータ型のサイズに等しいオフセットだけ増加します。例えば、ポインタがint*型の場合、ポインタをインクリメントするたびに4バイト増加します(int型が4バイトを占めると仮定した場合)。

注意すべき点として、ポインタ操作を使用する際は、ポインタが有効なメモリ領域を指していることを確認する必要があります。そうしないと、未定義動作やプログラムのクラッシュを引き起こす可能性があります。配列を操作する際は、特にポインタが配列の範囲外に出ないように注意する必要があります。

ポインタのデクリメント

C++では、ポインタはインクリメントだけでなく、デクリメントもできます。ポインタをデクリメントすることは、ポインタを前のメモリ位置を指すようにすることを意味します。ポインタのインクリメントと同様に、ポインタのデクリメントでも、ポインタが指すデータ型に基づいてポインタの値が自動的に調整されます。

以下は、ポインタをデクリメントする方法を示す簡単な例です:

例

#include <iostream> int main() { // 配列を定義する int arr[] = {10, 20, 30, 40, 50}; // 配列の2番目の要素を指すポインタを定義する int* ptr = &arr[1]; // ポインタが現在指す要素を出力する std::cout << "ポインタが現在指している要素:" << *ptr << std::endl; // ポインタをデクリメントする ptr--; // ポインタをデクリメントした後に指す要素を出力する std::cout << "ポインタをデクリメントした後に指す要素:" << *ptr << std::endl; return 0; }

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

指针当前指向的元素: 20
递减指针后指向的元素: 10

この例では、ポインタptrは最初、配列arrの2番目の要素を指しています。実行するとptr--、ポインタptrはデクリメントされ、配列の最初の要素を指すようになります。

ポインタをデクリメントするとき、ポインタの値は、ポインタが指すデータ型のサイズに等しいオフセットだけ減少します。例えば、ポインタがint*型の場合、ポインタをデクリメントするたびに4バイト減少します(int型が4バイトを占めると仮定した場合)。

ポインタの比較

C++では、ポインタの比較操作を使用して、2つのポインタが同じ位置を指しているかどうか、一方のポインタが指す位置が他方のポインタより前か後かなどを判断できます。ポインタの比較には主に以下の種類があります:

  • 等価性の比較 (==と!=)
  • 関係比較 (<, <=, >, >=)

等価性の比較

等価性の比較は、2つのポインタが同じ位置を指しているかどうかを確認するために使用されます。

例

#include <iostream>

int main() {
    int a = 10;
    int b = 20;
    int* ptr1 = &a;
    int* ptr2 = &a;
    int* ptr3 = &b;

    // ポインタが等しいかどうかを比較する
    if (ptr1 == ptr2) {
        std::cout << "ptr1 と ptr2 は同じ位置を指しています" << std::endl;
    } else {
        std::cout << "ptr1 と ptr2 は異なる位置を指しています" << std::endl;
    }

    if (ptr1 != ptr3) {
        std::cout << "ptr1 と ptr3 は異なる位置を指しています" << std::endl;
    } else {
        std::cout << "ptr1 と ptr3 は同じ位置を指しています" << std::endl;
    }

    return 0;
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

ptr1 和 ptr2 指向相同的位置
ptr1 和 ptr3 指向不同的位置

関係比較

関係比較は、一方のポインタが指す位置が他方のポインタより前か後かを判断するために使用されます。これは通常、ポインタが同じ配列の要素を指している場合に意味を持ちます。

例

#include <iostream>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr1 = &arr[1]; // 配列の2番目の要素を指す
    int* ptr2 = &arr[3]; // 配列の4番目の要素を指す

    // ポインタの相対的な位置を比較する
    if (ptr1 < ptr2) {
        std::cout << "ptr1 が指す要素は ptr2 が指す要素より前です" << std::endl;
    } else {
        std::cout << "ptr1 が指す要素は ptr2 が指す要素より前ではありません" << std::endl;
    }

    if (ptr2 > ptr1) {
        std::cout << "ptr2 が指す要素は ptr1 が指す要素より後です" << std::endl;
    } else {
        std::cout << "ptr2 が指す要素は ptr1 が指す要素より後ではありません" << std::endl;
    }

    return 0;
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

ptr1 指向的元素在 ptr2 指向的元素之前
ptr2 指向的元素在 ptr1 指向的元素之后

ポインタ比較の完全な例:

例

#include <iostream>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr1 = &arr[1]; // 配列の2番目の要素を指す
    int* ptr2 = &arr[3]; // 配列の4番目の要素を指す
    int* ptr3 = &arr[1]; // 配列の2番目の要素を指す

    // 等価性の比較
    if (ptr1 == ptr3) {
        std::cout << "ptr1 と ptr3 は同じ位置を指しています" << std::endl;
    } else {
        std::cout << "ptr1 と ptr3 は異なる位置を指しています" << std::endl;
    }

    if (ptr1 != ptr2) {
        std::cout << "ptr1 と ptr2 は異なる位置を指しています" << std::endl;
    } else {
        std::cout << "ptr1 と ptr2 は同じ位置を指しています" << std::endl;
    }

    // 関係比較
    if (ptr1 < ptr2) {
        std::cout << "ptr1 が指す要素は ptr2 が指す要素より前です" << std::endl;
    } else {
        std::cout << "ptr1 が指す要素は ptr2 が指す要素より前ではありません" << std::endl;
    }

    if (ptr2 > ptr1) {
        std::cout << "ptr2 が指す要素は ptr1 が指す要素より後です" << std::endl;
    } else {
        std::cout << "ptr2 が指す要素は ptr1 が指す要素より後ではありません" << std::endl;
    }

    return 0;
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

ptr1 和 ptr3 指向相同的位置
ptr1 和 ptr2 指向不同的位置
ptr1 指向的元素在 ptr2 指向的元素之前
ptr2 指向的元素在 ptr1 指向的元素之后

注意事項

  • 同じ配列範囲内での比較:関係比較(例:<, >, <=, >=)は、同じ配列の要素間で行う場合に意味があります。ポインタが同じ配列に属していない場合、関係比較の結果は未定義です。

  • ポインタがNULLの場合: ポインタを比較する前に、ポインタがヌルポインタ(nullptr)ではないことを確認してください。そうしないと、未定義動作を引き起こす可能性があります。

C++ ポインタ

その他の拡張