ポインタを使った数値の交換

CBeginner
オンラインで実践に進む

はじめに

C 言語のプログラミングでは、ポインタは強力な機能であり、直接メモリの場所にアクセスしてデータを変更することができます。ポインタの一般的な用途の 1 つは、第 3 の変数を使用せずに 2 つの変数間で値を交換することです。

この実験では、ポインタを使用して 2 つの数値を交換する C プログラムを作成する方法を学びます。この技術は、様々なプログラミングシナリオにおいて基本的なものであり、メモリ操作のためのポインタの実用的な使い方を示しています。

この実験では、最初からプログラムを作成し、コンパイルし、実行して交換の動作を確認する手順を案内します。

C 言語におけるポインタの理解

コーディングを始める前に、ポインタとは何か、および C 言語でどのように動作するかを理解しましょう。

ポインタとは何か?

ポインタは、別の変数のメモリアドレスを格納する変数です。ポインタは C 言語において不可欠です。なぜなら、メモリに直接アクセスでき、データの操作をより効率的に行うことができるからです。

ポインタの構文

C 言語では、アスタリスク (*) 記号を使用してポインタを宣言します。

int *ptr;    // 整数型へのポインタを宣言する

ポインタを扱う際には、2 つの重要な演算子を使用します。

  • アドレス演算子 (&) - 変数のメモリアドレスを取得する
  • 間接参照演算子 (*) - ポインタが保持するアドレスに格納されている値にアクセスする

最初のファイルを作成する

プロジェクトディレクトリにメインの C ファイルを作成して始めましょう。IDE を開き、main.c という名前の新しいファイルを作成します。

  1. ファイルエクスプローラーパネル(左側)で、/home/labex/project に移動します。
  2. 右クリックして「新しいファイル」を選択します。
  3. ファイル名を main.c とします。
  4. ファイルに次の基本構造を追加します。
#include <stdio.h>

int main() {
    // ここにコードを追加します

    return 0;
}

これにより、標準入出力ライブラリが含まれ、プログラムが正常に完了すると 0 を返すメイン関数を持つ簡単な C プログラムが作成されます。

交換プログラムの構造を作成する

これでポインタを理解したので、交換プログラムを段階的に構築しましょう。

変数とポインタの宣言

以下を宣言する必要があります。

  1. 交換したい値を保持する 2 つの整数型変数 (ab)
  2. ab のアドレスを格納する 2 つの整数型ポインタ (ptraptrb)
  3. 交換操作を支援する一時変数 (temp)

main.c ファイルを次のコードで更新します。

#include <stdio.h>

int main() {
    // 変数を宣言する
    int a, b;
    int *ptra, *ptrb;
    int temp;

    // ユーザーから入力を取得する
    printf("Enter value for a: ");
    scanf("%d", &a);

    printf("Enter value for b: ");
    scanf("%d", &b);

    // 元の値を表示する
    printf("\nOriginal values:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    // 次のステップでここにさらにコードを追加します

    return 0;
}

コードの理解

これまでに行ったことを分析しましょう。

  1. 交換したい値を保持する 2 つの整数 ab を宣言しました。
  2. ab のメモリアドレスを格納する 2 つの整数型ポインタ ptraptrb を宣言しました。
  3. 交換操作を支援する一時的な整数 temp を宣言しました。
  4. ユーザーに ab の値を入力するよう促すコードを追加しました。
  5. ab の元の値を表示するコードを追加しました。

scanf 関数では、アドレス演算子 (&) を使用して、入力値をメモリのどこに格納するかを関数に伝えていることに注意してください。

交換ロジックの実装

では、ポインタを使用して実際の交換ロジックを実装しましょう。

ポインタにアドレスを割り当てる

まず、ab のアドレスをそれぞれ ptraptrb に割り当てることで、ポインタが変数を指すようにします。

// ポインタにアドレスを割り当てる
ptra = &a;
ptrb = &b;

ポインタを使用した交換アルゴリズム

ポインタを使って値を交換するキーは、ポインタ自体ではなく、メモリ位置にある値を操作することです。以下のように行います。

  1. a の値(*ptra を介してアクセス)を一時変数 temp に格納する
  2. b の値(*ptrb を介してアクセス)を a に割り当てる(*ptra を使用)
  3. 一時的な値(a の元の値)を b に割り当てる(*ptrb を使用)

前のステップで指示された場所に次のコードを追加して、main.c ファイルを更新します。

#include <stdio.h>

int main() {
    // 変数を宣言する
    int a, b;
    int *ptra, *ptrb;
    int temp;

    // ユーザーから入力を取得する
    printf("Enter value for a: ");
    scanf("%d", &a);

    printf("Enter value for b: ");
    scanf("%d", &b);

    // 元の値を表示する
    printf("\nOriginal values:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    // ポインタにアドレスを割り当てる
    ptra = &a;
    ptrb = &b;

    // メモリアドレスを表示する(オプションだが理解に役立つ)
    printf("\nMemory addresses:\n");
    printf("Address of a: %p\n", ptra);
    printf("Address of b: %p\n", ptrb);

    // ポインタを使用して値を交換する
    temp = *ptra;    // a の値を temp に格納する
    *ptra = *ptrb;   // b の値を a に割り当てる
    *ptrb = temp;    // a の元の値を b に割り当てる

    // 交換後の値を表示する
    printf("\nAfter swapping:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    return 0;
}

交換ロジックの理解

交換がどのように機能するかを正確に理解しましょう。

  1. temp = *ptra; - * 演算子はポインタを間接参照し、メモリ位置にある値にアクセスします。この行は a の値を temp に格納します。
  2. *ptra = *ptrb; - これは b の値を a のメモリ位置に割り当て、実質的に a の値を変更します。
  3. *ptrb = temp; - これは a の元の値(temp に格納されている)を b のメモリ位置に割り当て、交換を完了します。

これらの操作の後、変数 ab は直接変更することなく値を交換しました。メモリ位置にある値のみを変更しました。

交換プログラムのコンパイルとテスト

これでプログラムが完成したので、コンパイルして実行し、結果を確認しましょう。

プログラムのコンパイル

プログラムをコンパイルするには、GNU C コンパイラ (gcc) を使用します。WebIDE でターミナルを開き、次のコマンドを実行します。

cd ~/project
gcc main.c -o swap_program

このコマンドは main.c ファイルをコンパイルし、swap_program という名前の実行可能ファイルを作成します。

プログラムの実行

では、プログラムが正しく値を交換するかどうかを確認するために、プログラムを実行しましょう。

./swap_program

ab の値を入力するように促されます。例えば、以下のように入力しましょう。

  • a = 5
  • b = 10

プログラムは以下を表示するはずです。

  • 元の値:a = 5, b = 10
  • a と b のメモリアドレス
  • 交換後の値:a = 10, b = 5

出力の理解

プログラムを実行すると、いくつかの出力セクションが表示されます。

  1. 元の値 - 交換前の値を表示します。
  2. メモリアドレス - 変数がメモリ内に格納されている場所を表示します(プログラムを実行するたびに異なります)。
  3. 交換後 - 交換操作後の値を表示します。

交換が一貫して機能することを確認するために、異なる入力値でプログラムを複数回実行してみてください。

内部ではどのように動作するのか?

メモリ内で何が起こるかを視覚化しましょう。

  1. 最初に、a = 5b = 10 の場合、それぞれ独自のメモリ位置を持っています。
  2. ptraa のメモリ位置を指しています。
  3. ptrbb のメモリ位置を指しています。
  4. 交換中:
    • tempptra の値(5)を取得します。
    • ptra の値は ptrb の値(10)に変更されます。
    • ptrb の値は temp(5)に変更されます。
  5. 交換後、a = 10b = 5 になり、実質的に値が交換されます。

これはポインタの強力さを示しています。ポインタを使用すると、メモリ位置を直接操作することで間接的に値を変更することができます。

まとめ

この実験では、C 言語でポインタを使用して 2 つの変数の値を交換する方法を学びました。カバーされた主要な概念は以下の通りです。

  1. ポインタ: 他の変数のメモリアドレスを格納する変数
  2. メモリアドレス: データが格納されるコンピュータメモリ内の一意の場所
  3. ポインタ操作:
    • 変数のメモリアドレスを取得するためのアドレス演算子 (&)
    • メモリアドレスの値にアクセスするための間接参照演算子 (*)
  4. 交換アルゴリズム: 一時変数とポインタを使用して値を交換する

このテクニックは C 言語プログラミングの基本的な概念であり、メモリ操作におけるポインタの強力さを示しています。ソートアルゴリズム、データ構造操作、関数実装など、様々なプログラミングシナリオに適用できます。

メモリアドレスを介してデータを操作する方法を理解することで、C 言語プログラミングとコンピュータメモリの概念を習得する重要な一歩を踏み出しました。